Agent Design Standard
Agent Design Standard Version: 2.0 — April 28, 2026 Purpose: Reference for creating and auditing RedKey agents. All new agents must use Agent Card format. Prose personas are legacy — do not create new ones. Reference implementation: definitions/cards/quinn.json — the canonical reference Card. The Format: Agent Card (card version 1.0) Every new agent is defin...
Version: 2.0 — April 28, 2026 Purpose: Reference for creating and auditing RedKey agents. All new agents must use Agent Card format. Prose personas are legacy — do not create new ones.
Reference implementation: definitions/cards/quinn.json — the canonical reference Card.
---
Every new agent is defined as an Agent Card JSON file in definitions/cards/<slug>.json and synced to Supabase via scripts/sync-agent-cards.js.
The Card replaces the prose persona field. Prose personas are supported for backwards compatibility but must not be created for new agents.
| Field | Required | Rule |
|---|---|---|
| card_version | Yes | Must be "1.0" |
| identity.slug | Yes | Matches the agent's slug in agent_definitions |
| identity.name | Yes | Display name |
| identity.department | Yes | dev / ops / marketing / sales / platform |
| identity.reports_to | Yes | Agent slug or "human" |
| identity.model | Yes | Exact model ID |
| scope | Yes | One sentence. What the agent owns AND what it doesn't. |
| capabilities | Yes | What the agent can do — one phrase per item |
| constraints | Yes | "I never X" format — declarative, not advisory. Min 3. |
| escalation_rules | Yes | At least one rule. Must reference real role slugs. |
| output_types | Yes | References Wire output contract slugs |
| working_style | Yes | 3 sentences max. How the agent approaches work. |
| voice.description | Yes | 1-2 sentences on communication style |
| voice.example | Yes | One concrete example of agent output |
| values | Yes | What the agent optimises for |
Every Card must implicitly answer these:
| Question | Card field |
|---|---|
| Who are you? | identity + scope |
| Where do you run? | platform-env shared skill (injected automatically — do not repeat in Card) |
| What's your first move? | working_style first sentence |
| What do you do? | capabilities |
| How do you know you're done? | output_types + escalation_rules |
| When do you stop and ask for help? | escalation_rules |
| What do you hand off? | output_types |
| What do you never do? | constraints |
| Who gets problems? | escalation_rules[].route_to |
Write "I never X" not "avoid X" or "try not to X". Declarative prohibitions hold more reliably than advisory prose.
Wrong: "You should avoid committing directly to main" Right: "I never commit directly to main or marketplace"
Every escalation rule must reference a real, currently-deployed role slug or agent slug. Check scripts/lib/dispatch.js ROLE_TOPIC_IDS for valid role slugs.
---
Agent-specific execution procedures (step-by-step flows) live in capabilities/skills/<agent>-<protocol>.md, not in the Card. The Card is an identity document — not a manual.
| Content type | Location |
|---|---|
| Who I am, constraints, voice | Agent Card (definitions/cards/<slug>.json) |
| Step-by-step execution procedures | Agent-specific skill (capabilities/skills/<slug>-protocol.md) |
| VPS environment | capabilities/skills/platform-env.md (shared, auto-injected) |
| Inbox read/write protocol | capabilities/skills/inbox-protocol.md (shared, auto-injected) |
| Done/blocked criteria | output_contract in Wire Brief |
Both platform-env and inbox-protocol are injected for all agents — do not repeat their content in any Card or skill.
---
All A2A messages are Wire messages. See definitions/wire/ for schemas.
| Message | Producer | Consumer |
|---|---|---|
| Wire Brief | dispatch.js | runner.py → agent system prompt |
| Wire Inbox | hedera-listener.py, hcs-post-server.js | runner.py → agent inbox section |
| Wire Complete | runner.py | hedera-listener.py, Mindy |
| Wire Blocked | runner.py | hedera-listener.py, Iris (blocker_type routing), Mindy |
| Wire Claim | runner.py | hedera-listener.py |
Rule: agent output fields (summary, reason) are the only prose in a Wire message. All other fields are typed.
---
- [ ] Write
definitions/cards/<slug>.jsonusingdefinitions/cards/TEMPLATE.json - [ ] Add agent to
definitions/agents/<slug>.json(slug, name, department, model, schedule_seconds, roles, skills, plugins) - [ ] Add role entry to
scripts/lib/dispatch.jsROLE_TOPIC_IDS if adding a new role - [ ] Run
node --env-file=.env scripts/sync-agent-cards.js --slug <slug> - [ ] Create a systemd unit file on VPS if the agent runs as a daemon
- [ ] Verify runner picks up the Card: check
journalctl -u redkey-<slug>for "assembling prompt from Card"