Skip to content

feat(engine,dashboard): agent import/export JSON — agents-as-code workflow (#94) - #98

Merged
rlagowski merged 3 commits into
developfrom
issue/94-agent-import-export
Apr 28, 2026
Merged

feat(engine,dashboard): agent import/export JSON — agents-as-code workflow (#94)#98
rlagowski merged 3 commits into
developfrom
issue/94-agent-import-export

Conversation

@rafeekpro

Copy link
Copy Markdown
Collaborator

Summary

Adds `GET /agents/{id}/export` and `POST /agents/import` so an agent's full configuration can move between DAP installations or be checked into git. Closes the last v0.7 (Agent management UX) issue.

Three concrete use cases:

  • Backup before risky edits — export, edit, restore by importing if it breaks.
  • Sharing between teams / installations — copy an agent from one engine to another without hand-copying config.
  • Agents-as-code — version agent definitions in git alongside the codebase they automate. Code review for prompt template changes.

Secrets stay in env — exported JSON contains no API keys; `api_key_env` references inside `runtime_config` round-trip as plain strings.

Engine

  • `AgentExportPayload` mirrors `AgentCreate` minus per-installation fields (id, version, timestamps, archived_at). Reuses the field-list validators from Engine: typed input/output schemas per agent (replaces ROLE_FIELDS) #58.
  • `AgentExport` wraps the payload with `schema_version` (`agent-export/1`) for forward-compat.
  • `GET /agents/{id}/export` returns the portable shape (404 on unknown id).
  • `POST /agents/import` validates `schema_version`, runs Pydantic validation (same as create), checks `runtime_id` against the registry, delegates to `repo.create_agent`. 201 + Agent on success, 422 on every malformed-input path.

Dashboard

  • `exportAgent` / `importAgent` API client functions; `useImportAgent` mutation hook.
  • `/agents/[id]` detail page: `Export JSON` button next to Edit / Clone / Archive. Triggers `{slug}.agent.json` browser download (slug derived from name; falls back to id prefix if empty).
  • `/agents` list: `Import JSON` button next to `New agent`. Hidden file input + click → cheap shape check → POST → routes to imported detail. Errors surface as `role="alert"` line above the table.

Test plan

  • `uv run pytest tests/smoke/` — 397 passed (12 new in `test_agent_import_export.py`)
  • `uv run ruff check apps packages` — clean
  • `uv run ruff format --check apps packages tests` — clean
  • `uv run mypy apps packages tests` — Success: no issues found in 93 source files
  • `pnpm tsc --noEmit` (dashboard) — clean
  • `pnpm lint` (eslint) — clean

12 new engine tests cover: portable export shape (no per-install fields, all portable fields present), export 404, round-trip preservation of all portable fields, and 9 distinct 422 paths (missing schema_version, wrong schema_version, extra top-level field, extra agent field, unknown runtime_id, unknown PipelineState field in input_schema, unknown field in output_schema, blank name, zero timeout_ms).

Out of scope

  • Bulk export/import (zip with multiple agents) — sensible follow-up.
  • Pipeline / project export-import — referenced agent_ids complicate portability (would need either id remapping or co-export).
  • CLI wrapper (`dap agents export | import`) — endpoints are CLI-friendly; wrapper is a follow-up if muscle memory matters.

🤖 Generated with Claude Code

…kflow (#94)

Adds ``GET /agents/{id}/export`` and ``POST /agents/import`` so an
agent's full configuration can move between DAP installations or be
checked into git. Last issue in v0.7 (Agent management UX).

## Engine

- ``AgentExportPayload`` mirrors ``AgentCreate`` field-by-field minus
  per-installation fields (id, version, timestamps, archived_at).
  Reuses the same ``input_schema`` / ``output_schema`` validators
  from #58 so an exported agent is also creatable directly via
  ``POST /agents``.
- ``AgentExport`` wraps the payload with ``schema_version``
  (``agent-export/1``) so future incompatible format changes can be
  detected at import time rather than silently producing odd state.
- ``AgentImportRequest`` validates ``schema_version`` matches and the
  agent payload is well-formed.
- ``GET /agents/{id}/export`` reads the current agent and returns the
  portable shape. 404 on unknown id.
- ``POST /agents/import`` validates ``runtime_id`` against the
  runtime registry (engine-specific check, can't be a Pydantic
  validator) and delegates to ``repo.create_agent`` for everything
  else. Same versioning, same response shape, same field validators.

Status codes:

- 201 — agent created (v1).
- 422 — schema_version mismatch, unknown runtime_id, unknown
  PipelineState field in input/output_schema, blank name, zero
  timeout, extra top-level or per-agent field.
- 404 — export of unknown agent id.

## Dashboard

- API client gains ``exportAgent(id)`` and ``importAgent(payload)``;
  TS ``AgentExport`` / ``AgentExportPayload`` types mirror the
  engine shapes.
- ``useImportAgent()`` hook (mutation, invalidates the agents list).
- ``/agents/[id]`` detail page: ``Export JSON`` button next to
  Edit / Clone / Archive. Triggers a browser download as
  ``{slug}.agent.json`` (slug derived from agent name; falls back
  to agent id prefix if name slugifies to empty).
- ``/agents`` list: ``Import JSON`` button next to ``New agent``.
  Hidden file input + click → user picks JSON → cheap shape check
  on the client → POST → routes to the imported agent's detail.
  Errors (parse failures, server 422) surface as a destructive
  ``role="alert"`` line above the table.

## Tests

12 new tests in ``test_agent_import_export.py``:

- export returns the portable shape (no per-installation fields,
  every portable field present);
- export 404 for unknown id;
- round-trip preserves all portable fields (export → import → diff);
- import 422 on missing schema_version, wrong schema_version, extra
  top-level field, extra agent field, unknown runtime_id, unknown
  field name in input_schema, unknown field name in output_schema,
  blank name, zero timeout_ms.

## Out of scope

- Bulk export/import (zip with multiple agents).
- Pipeline / project export-import (referenced agent_ids complicate
  portability — would need either ID remapping or co-export).
- CLI wrapper (``dap agents export | import``) — endpoints are
  CLI-friendly already; CLI command is a follow-up if anyone
  wants the muscle memory.

Closes #94.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 28, 2026 14:03

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an agents-as-code workflow by introducing versioned JSON import/export for agent configurations in the engine API and wiring corresponding UI actions in the dashboard.

Changes:

  • Engine: introduce AgentExport* request/response schemas + GET /agents/{id}/export and POST /agents/import.
  • Dashboard: add API client + hooks for import/export, plus “Import JSON” (list) and “Export JSON” (detail) UI flows.
  • Tests: add smoke coverage for round-trip behavior and a set of 422 validation paths.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/smoke/test_agent_import_export.py New smoke tests for export shape, round-trip import, and multiple invalid-import cases.
apps/engine/src/dap_engine/api/schemas.py Adds versioned import/export Pydantic schemas and schema_version validation.
apps/engine/src/dap_engine/api/agents.py Implements POST /agents/import and GET /agents/{id}/export endpoints.
apps/dashboard/src/lib/api/types.ts Adds TS types/constants for the agent export/import payload shapes.
apps/dashboard/src/lib/api/client.ts Adds exportAgent and importAgent client functions.
apps/dashboard/src/hooks/api.ts Adds useImportAgent mutation and cache invalidation.
apps/dashboard/src/app/agents/page.tsx Adds “Import JSON” UI with hidden file input + preflight shape check + mutation.
apps/dashboard/src/app/agents/[id]/page.tsx Adds “Export JSON” UI and browser download logic with slugified filename.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/smoke/test_agent_import_export.py Outdated
Comment thread apps/engine/src/dap_engine/api/agents.py Outdated
Comment thread apps/engine/src/dap_engine/api/agents.py
Comment thread apps/dashboard/src/app/agents/page.tsx Outdated
… guards

- Export endpoint scrubs runtime_config keys matching credential
  patterns (api_key/token/secret/password/credential, recursive)
  before serialising — defence in depth against literal keys leaking
  into a portable artifact.
- Import endpoint round-trips AgentExportPayload through
  model_dump → AgentCreate.model_validate so future fields flow
  automatically without editing a manual mapping; ValidationError
  surfaces as 422.
- Test fixture switches to TemporaryDirectory context manager so
  the per-test SQLite file is cleaned up.
- isAgentExportShape rejects null/array values and uses a single
  narrowed candidate object for the shape checks.

Adds a smoke test that exports an agent with deliberate
api_key / auth_token / nested.openai_api_key entries and asserts
each is replaced with `<redacted>`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@rlagowski
rlagowski merged commit a8d59c3 into develop Apr 28, 2026
2 checks passed
@rlagowski
rlagowski deleted the issue/94-agent-import-export branch May 10, 2026 11:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants