Agent Projects
An agent that matters deserves the same treatment as code: version control, code review, tests, and a deploy step. An agent project is a git repository where agent specs live as JSON files, and a docana.manifest.json tells the CLI which file maps to which agent in Docana.
Start from the Template
The fastest way in is the template repository — it has the layout, a working example agent, an eval, and CI already wired:
github.com/DocanaAI/docana-agent-template — click "Use this template", clone, run docana login, set your application ID, and docana push -y.
The template also ships an AGENTS.md for AI coding assistants (Claude Code, Cursor, ...), so they follow the validate → diff → push workflow and the agent design rules from docana help ai instead of guessing.
A typical project looks like:
my-project/
├── docana.manifest.json # Maps files to agents in Docana
├── agents/
│ └── main.agent.json # Agent specs (export payloads)
├── routines/
│ └── daily-report.json # Scheduled routines, if you use them
└── evals/
└── eval-*.json # Test cases, synced with the agent
The Manifest
One docana.manifest.json per project. It names your entities, points each at a source file, and records which remote agent each file tracks:
{
"apiVersion": "docana/v1",
"project": {
"name": "my-project",
"applicationId": 42
},
"defaults": { "target": "main" },
"targets": {
"main": { "entities": ["agent:main", "routine:daily-report"] }
},
"entities": {
"agent:main": {
"type": "agent",
"source": "agents/main.agent.json",
"remoteId": "cmly7kpth0019x5c9dyn3hegk",
"agent": {
"pullEvalDir": "evals",
"pushEvalFiles": ["evals/*.json"]
}
},
"routine:daily-report": {
"type": "routine",
"source": "routines/daily-report.json",
"remoteId": "cmohsze35003m21c9mu1jxfwc",
"routine": { "agentRef": "agent:main" }
}
}
}
Field by field:
| Field | What it does |
|---|---|
apiVersion | Always docana/v1. |
project.name | A label for the project. |
project.applicationId | Default application for every entity. Override per entity with applicationId, or per command with --app-id. |
defaults.target | Which target plain docana push / pull / validate operate on. |
targets | Named groups of entity keys, so one command deploys a coherent set. |
entities | The map of everything the project manages. Keys are yours to choose; agent:name and routine:name is the convention. |
And per entity:
| Field | What it does |
|---|---|
type | agent or routine. |
source | Path to the JSON file, relative to the manifest. |
remoteId | The entity's ID in Docana. Set it after the first push — it's what lets docana pull and docana agents diff find the deployed version. |
applicationId | Overrides project.applicationId for this entity. |
agent.pushEvalFiles | Glob patterns of eval files to bundle into the agent's test registry on push. |
agent.pullEvalDir | Directory where docana pull writes the registry's evals, one file each. |
agent.pullEvalFormat | spec (default, just the eval spec) or full (name, description, and enabled flag too). |
routine.agentRef | Entity key of the agent the routine runs on, e.g. "agent:main". |
Push, Pull, Validate
The generic commands read the manifest and accept a selector — an entity key, a target name, or a wildcard:
docana push -y # default target
docana push agent:main -y # one entity
docana push --target main -y # a named target
docana push "agent:*" -y # every agent
docana pull # write deployed state back to your files
docana validate # schema-check every source file
docana push updates the agent's working version; users keep talking to the live version until you promote it. Add --publish to do both in one step, once evals pass:
docana push -y --publish
Evals Live in the Repo
With pushEvalFiles set, every push replaces the agent's test registry with the eval files in git — so a pull request that changes a prompt can (and should) also change the tests, and reviewers see both together. pullEvalDir completes the round trip: evals someone added in the UI come back to disk on docana pull.
Each eval file is one scenario:
{
"name": "Stays concise",
"enabled": true,
"evalSpec": {
"steps": [
{ "type": "user", "text": "What are your support hours?" },
{
"type": "smartAssertion",
"expectedOutput": "A short answer that offers further help.",
"evaluationCriteria": "Concise, no fabricated facts.",
"minScore": 7
}
]
}
}
See Testing Agents for what goes into a good test case.
Dev and Production
Don't test against the application your users are on. Two patterns that work well together:
- Separate applications — iterate against a dev application, and only push to the production one when evals pass.
- Side-by-side manifests — one manifest per environment, same source files, different
applicationIdandremoteIds:
docana push -y # dev (docana.manifest.json)
docana push -y --manifest docana.manifest.prod.json # production
CI
Because everything is files plus a CLI, CI is ordinary: validate on every pull request, eval before merge. The template ships a GitHub Actions workflow that does the first part — set DOCANA_API_URL and DOCANA_API_KEY as repository secrets and it runs docana validate "*" on each PR.
Next Steps
- CLI — everything else the
docanacommand does - Testing Agents — the eval concepts behind the test registry
- Routines — the scheduled runs a
routineentity manages - Docana MCP — edit these same files with an AI coding assistant that knows your workspace