Skip to main content

Agent Development Guide

Version française : ../../fr/guides/agent-development.md

This guide shows how to write, validate, test, register, run, version and retire an agent of the Navin Platform. It is for developers with the developer or tenant_admin role; suspending and killing an agent needs tenant_admin or security_officer. Count about one hour for a first agent from the template.

Concept​

An agent is a versioned manifest of kind Agent plus code run by the Navin runtime. The Control Plane stores every version of the manifest, starts the runs, applies the policies and the budget, and records each step. The agent never calls a model provider directly: every model call goes through the AI gateway, every tool call through the tool gateway, and every secret stays in the Credential Broker.

The life cycle of an agent is: active (new runs accepted), suspended (reversible kill switch, new runs refused) and killed (final, can never be resumed).

Manifest​

An agent is described by a manifest of kind Agent (contracts/v1/agent-manifest.schema.json): runtime (engine, entrypoint, limits), models (effort, max_output_tokens), memory, permissions (data_classification_max, scopes), autonomy (level, max_steps, max_subagents, max_depth, human_approval_for), evaluation and observability. The template sdks/python/src/enterprise_ai/templates/agent-basic/agent.yaml is a valid example.

enterprise-ai create agent invoice-agent --template rag-agent
enterprise-ai validate -f invoice-agent/agent.yaml

Manifest fields​

FieldTypeRequiredDescription
apiVersionstringyesAlways enterprise-ai.io/v1.
kindstringyesAlways Agent.
metadata.namestringyesDNS like identifier, lowercase, up to 128 characters.
metadata.versionsemveryesVersion of the manifest; a published version is immutable.
metadata.ownerstringyesAccountable team or e-mail (3 to 200 characters).
metadata.description, metadata.labelsstring, mapnoFree description and labels (the environment label is set by deploy).
spec.descriptionstringyesWhat the agent does.
spec.purposestringnoBusiness purpose, passed to the agent.run policy.
spec.risk_levelenumnominimal, limited, high or unacceptable (refused at registration).
spec.identityobjectnospiffe_id and service_account of the workload.
spec.runtimeobjectyesengine (langgraph, temporal, custom), entrypoint, image, sandbox (none, gvisor, kata, wasm), limits.
spec.modelsarrayyesEach item: model_id, role (primary, fallback, summarizer, embedding, judge, vision, speech), effort (none to max), max_output_tokens.
spec.toolsarraynoEach item: ref (such as tool:crm-search@1.2.0), scopes, requires_approval.
spec.mcp_servers, spec.skills, spec.connectors, spec.knowledge_bases, spec.channelsarraynoTyped references to the objects the agent may use; a skill not listed here is refused by the Skill Loader.
spec.memoryobjectnosession, persistent, ttl_days.
spec.permissionsobjectyesdata_classification_max (public < internal < confidential < restricted < secret), scopes, allowed_regions.
spec.autonomyobjectyeslevel (assisted, supervised, autonomous), max_steps, max_subagents, max_depth, human_approval_for.
spec.subagentsarraynoReferences of the agents it may delegate to.
spec.budgetsobjectnomax_cost, max_input_tokens, max_output_tokens, max_requests, max_tool_calls, max_duration_seconds, period.
spec.schedules, spec.triggersarraynoPlanned and event driven starts.
spec.evaluationobjectnosuites (references) and block_on_failure; read by the quality gate of deploy.
spec.observabilityobjectnotrace_sampling (0 to 1) and log_prompts (none, hashed, redacted, full).

Before you begin​

  • The Python SDK and its CLI are installed and logged in: enterprise-ai doctor reports no FAIL.
  • Your account has the developer role in the tenant, and the scope agents:run to start runs.
  • The model you reference is approved in the model registry of the tenant.

Steps​

  1. Create the project from a template. The template gives a manifest, the code, a versioned prompt, an OPA policy and tests that already pass; starting from it avoids an invalid first manifest.

    enterprise-ai create agent invoice-agent --template agent-basic

    The templates are agent-basic, rag-agent and secure-agent (an alias of agent-basic).

    Expected result: the command lists the created files and ends with the manifest marked valid against agent-manifest.

    If it fails: exit code 1 with "exists" means the folder is already there; add --force or pick another name.

  2. Edit the manifest. Set spec.description, the model, the scopes and the autonomy. Keep permissions.data_classification_max and scopes as small as the task allows: they bound every skill, tool and connector the agent can load. You can also edit it in Agents > Registry > agent > Manifest.

    Expected result: the manifest describes only what the agent needs.

    If it fails: see the field table above; a skill or tool that the agent will call must be listed in spec.

  3. Validate the manifest. The CLI checks it against the v1 contract offline, before any call to the Control Plane.

    enterprise-ai validate -f invoice-agent/agent.yaml

    Expected result: exit code 0, the document is valid.

    If it fails: exit code 1 lists each invalid field with its JSON path; fix it and run the command again.

  4. Test locally. Run the unit tests and the OPA tests of the project, then an evaluation suite on the entrypoint.

    cd invoice-agent
    python -m pytest -q tests
    enterprise-ai test authz
    enterprise-ai test -f suite.yaml --entrypoint agent:build

    suite.yaml: an evaluation suite of the project (cases and metrics). See the testing guide.

    Expected result: every test passes and the suite reports passed.

    If it fails: enterprise-ai test returns 1 when the evaluation is below target, or when opa or fga is not installed.

  5. Register the agent. POST /v1/agents creates the agent or adds a version and makes it current. The caller becomes the ReBAC owner.

    enterprise-ai apply -f agent.yaml

    Expected result: apply_status is created, version_added or unchanged.

    If it fails: 422 invalid_manifest (contract), 422 agent_risk_unacceptable (risk level), 409 version_immutable (same version, other content: raise metadata.version).

  6. Deploy through the quality gate. deploy validates, applies, runs the gate POST /v1/evaluations/gates/check on the suites of spec.evaluation, then sets the environment label.

    enterprise-ai deploy agent -f agent.yaml --env staging

    Expected result: the agent is deployed in staging.

    If it fails: exit code 1 means the quality gate refused the promotion; the gate report is printed.

  7. Start a run. POST /v1/agents/{agent_id}/runs creates a run and returns its Execution Contract. The policy agent.run is evaluated first and the manifest budget is applied. In the portal: Agents > Registry > agent > Start run.

    enterprise-ai run start invoice-agent --task '{"invoice_media_id": "med_01HZX3K9"}' --follow
    enterprise-ai runs list --agent agt_ap --state running

    Expected result: the run goes pending, running, then succeeded; --follow streams its events.

    If it fails: 409 agent_not_active, 403 policy_denied, 422 invalid_budget; with --follow, exit code 1 means the run ended failed, cancelled or timed_out.

  8. Publish a new version. Raise metadata.version, validate, then apply again. GET /v1/agents/{agent_id}/versions lists every version, newest first, with current set on the one in use.

    Expected result: apply_status is version_added; new runs use the new version.

    If it fails: 409 version_immutable means the version number was not raised.

  9. Suspend, resume, kill or delete. POST /v1/agents/{agent_id}/suspend moves the agent and its active runs to suspended. POST /v1/agents/{agent_id}/resume opens an approval (202 pending_approval). POST /v1/agents/{agent_id}/kill cancels every active run and ends the agent for good. DELETE /v1/agents/{agent_id} removes the agent and its versions. In the portal: Agents > Registry > agent > Suspend, Resume or Kill.

    client.agents.suspend("agt_ap", reason="incident INC-42")
    client.agents.resume("agt_ap")

    Expected result: the answer lists affected_runs.

    If it fails: 409 agent_killed (already killed), 409 kill_switch_active (a SOC containment holds the agent), 409 agent_has_active_runs on delete.

danger

Kill is final: a killed agent can never be resumed. Use suspend for an investigation.

Register and run​

POST /v1/agents creates the agent, GET /v1/agents/{agent_id}/versions lists its versions, POST /v1/agents/{agent_id}/runs starts a run, POST /v1/runs/{run_id}/heartbeat reports a long run (action stop: checkpoint then exit), POST /v1/agents/{agent_id}/suspend suspends it.

import yaml
agent = client.agents.create(yaml.safe_load(open("agent.yaml")))
run = client.agents.run("agt_ap", task={"invoice_media_id": "med_01HZX3K9"}, idempotency_key="inv-2291")
run = client.runs.get(run["id"])

A repeated Idempotency-Key returns the first run. A long run sends heartbeats: the answer action is continue, or stop with a reason (run_cancelled, run_terminal, run_suspended, agent_killed, agent_suspended). On stop, write a checkpoint and exit; POST /v1/runs/{run_id}/resume restarts it with from_last_checkpoint, restart_step or restart_run.

Rules​

No direct call to a model provider: everything goes through the gateway. No secret in the code or in the manifest. A sub-agent always receives a restricted delegation. The Navin runtime is AgentLoop, AgentRunner, SubagentManager, RunPlan and MessageBus; LangGraph and Temporal are optional adapters.

enterprise-ai deploy agent -f agent.yaml --env staging
enterprise-ai runs list --agent agt_ap --state running

Verify​

enterprise-ai agent inspect invoice-agent shows the agent as the Control Plane stores it: status active, the manifest of the current version and runs, the number of runs per state.

Troubleshooting​

SymptomCauseFix
422 invalid_manifestThe manifest does not match contracts/v1/agent-manifest.schema.json.Run enterprise-ai validate -f agent.yaml and fix the fields listed.
422 agent_risk_unacceptablespec.risk_level is unacceptable.Such an agent cannot be registered; reduce its scope.
409 version_immutableThe version exists with another content.Raise metadata.version.
409 agent_not_activeThe agent is suspended or killed.Resume it (approval) or register a new agent.
403 policy_deniedThe agent.run policy refused the run.Read the decision in Security and governance; check the risk, purpose and classification.
422 invalid_budgetThe request tried to loosen the manifest budget.A request can only tighten budgets.
409 idempotency_conflictThe same Idempotency-Key was used for another agent.Use one key per logical request.
409 subagent_depth_exceeded, subagent_count_exceededDelegation beyond max_depth or max_subagents.Raise the autonomy limits or reduce the delegation.
409 run_not_resumableThe run failed on budget_exceeded, max_steps_exceeded, killed or approval_rejected.Resume with restart_run.
409 no_checkpointNo checkpoint to resume from.Use restart_step or restart_run.

Next steps​