Skip to content
All posts
SeriesD2D Agentic Architecture· Part 2

Inside a D2D Agent: Manifest, System Prompt, Tool Contract

July 13, 2026 · PlayCISO
Put it into practice
AI Agent Guardrail Planner
Describe your agent and get a layered guardrail plan with examples, what each control does not stop, and OWASP LLM and Agentic Top 10 mapping.
Open the tool →

In the D2D overview we covered the coordinator, worker, and killer node model. Now let's get concrete: what do the actual files look like inside one of these agents?

The Three-File Pattern

Every D2D agent — whether coordinator or worker — is fully described by three artifacts. This is what makes D2D composable: you can swap out an agent's model, budget, or tool set by editing these files, without touching the orchestration layer.

1. manifest.yaml

name: cve-enrichment-worker
domain: vuln-management
model: claude-haiku-4-5
token_budget: 8000
heartbeat_interval_s: 30
max_retries: 2
tools:
  - nvd_lookup
  - epss_score
  - exploitdb_search
  - jira_create_ticket
output_schema: ./schemas/cve-enrichment-result.json
escalation:
  on_timeout: killer
  on_schema_fail: killer
  on_retry_exhausted: human

Key fields to notice:

  • domain — scopes this worker; the coordinator uses this to route tasks
  • token_budget — the killer node monitors this; if exceeded, the agent is terminated
  • output_schema — every worker output is validated against this before it's accepted by the coordinator
  • escalation — explicit rules: what goes to the killer, what goes to a human

2. system.md (the agent's system prompt)

# CVE Enrichment Worker

You are a specialist agent for enriching CVE data. You operate within the vuln-management domain.

## Your job
Given a CVE ID and an optional affected asset, you must:
1. Look up the CVE in NVD and return the CVSS score, vector, and description
2. Retrieve the EPSS score (probability of exploitation in the wild)
3. Search ExploitDB for any public exploit code
4. Create a Jira ticket if CVSS >= 8.0 AND EPSS >= 0.3

## Constraints
- You may ONLY call tools listed in your manifest. Never attempt to call unlisted tools.
- If NVD returns no result, emit status: "not_found" and stop.
- Do not infer or guess CVE details. Only use data returned by tools.
- Your output must conform to the output schema exactly.

## Output format
Return a single JSON object matching the schema at schemas/cve-enrichment-result.json.
Do not include any prose outside the JSON object.

The system prompt is deliberately narrow. A worker that can "infer or guess" is a liability — it will hallucinate CVE details under time pressure. The constraint is a safety property, not a limitation.

3. Tool definitions (tools.json)

{
  "nvd_lookup": {
    "description": "Query the NVD API for a CVE by ID",
    "input": { "cve_id": "string" },
    "output": { "cvss_score": "number", "cvss_vector": "string", "description": "string" },
    "endpoint": "https://services.nvd.nist.gov/rest/json/cves/2.0"
  },
  "epss_score": {
    "description": "Retrieve EPSS exploitation probability for a CVE",
    "input": { "cve_id": "string" },
    "output": { "epss": "number", "percentile": "number" },
    "endpoint": "https://api.first.org/data/v1/epss"
  }
}

Tool definitions are the trust boundary. The agent runtime enforces that the agent can only call tools declared here, with input shapes that match the schema. There is no ambient tool access.

The Coordinator's Routing Table

The coordinator keeps a routing table that maps incoming task types to worker domains:

routes:
  - task_type: enrich_cve
    domain: vuln-management
    worker: cve-enrichment-worker
  - task_type: query_siem
    domain: detection
    worker: siem-query-worker
  - task_type: notify_slack
    domain: comms
    worker: slack-notify-worker
  - task_type: human_review
    domain: null
    escalate: pagerduty

The Killer Node's Watch Loop

The killer node runs a simple watch loop against all active workers:

every 10s:
  for each active worker:
    if now - last_heartbeat > heartbeat_interval * 2:
      emit KILL(worker_id, reason="timeout")
    if worker.tokens_used > worker.token_budget:
      emit KILL(worker_id, reason="budget_exceeded")
    if worker.output_schema_failures > 2:
      emit KILL(worker_id, reason="schema_fail")

When a KILL is emitted, the coordinator decides whether to retry (up to max_retries) or escalate to a human. The worker's last known state — including any intermediate tool outputs — is preserved in the task log for post-mortem.

Why This Pattern Is Auditable

Every message in the system is structured and logged: task assignment, heartbeat, tool call, tool result, output, KILL signal. An incident investigator can reconstruct exactly what every agent did, why it did it, and what the coordinator decided at each step. That's the audit trail a CISO can actually show to a board.

Next in this series: how the coordinator handles mission planning and re-planning under partial failure.

Frequently asked questions

What three files describe a D2D agent?

A manifest.yaml declaring name, domain, model, token budget, heartbeat interval, tools and escalation rules; a system.md system prompt with the role, constraints and output schema; and tool definitions in tools.json that set the exact API surface the agent can call.

Why are the files useful?

The post says the three-file pattern makes D2D composable: you can swap an agent's model, budget or tool set by editing the files without touching the orchestration layer.

What does the manifest's escalation field do?

It sets explicit rules for what goes to the killer node and what goes to a human. In the post's example, a timeout or a schema failure goes to the killer and an exhausted retry count goes to a human.

How does the killer node's watch loop work?

Every 10 seconds it checks each active worker, issuing a KILL if the last heartbeat is older than twice the heartbeat interval or if tokens used exceed the token budget.

Ready to practise the decisions these articles describe?

Run your first Cyber War Room free →

Pro