Owners and mandates
Make sure no agent goes live without someone accountable for it, and give each agent a mandate, its purpose, success criteria, the systems it may call and its budget.
- Publish an agent only with an owner
- Write an agent's mandate
- Limit an agent to the systems its mandate names
- Migrate existing agents
No owner, no deploy
Publishing an agent (its card published, so people and other agents can reach it) when its registry entry names no owner is handled by TICKETIQ_AGENT_PUBLISH_OWNER:
| Mode | Effect |
|---|---|
assign (default) | The person publishing becomes its owner, audited as agent.publish.owner_assigned. No agent is deployed unowned and nobody gains a step |
require | The publish is refused with 422 until the registry entry names an owner (agent.publish.unowned) |
off | No check at publish |
The owner is assigned only after the posture and red-team gates let the publish through, so a refused publish changes nothing. A version restore that publishes is handled the same way.
TICKETIQ_REGISTRY_REQUIRE_OWNER (default false) is separate: it refuses any registry save that leaves the entry without an owner.
The mandate
A mandate says what the agent is for and the limits it works inside.
PUT /api/governance/mandates/{agent}
{
"purpose": "Answer IT questions from staff",
"success_criteria": ["Resolved without a person", "Answered within 2 minutes"],
"allowed_systems": ["jira", "servicenow"],
"budget_usd": 200,
"budget_period": "month"
}| Field | What it does |
|---|---|
purpose, success_criteria | What the agent is for and how its outcome is judged. Up to 10 criteria |
allowed_systems | The MCP servers it may call. See below |
budget_usd, budget_period | Saved as the agent's own budget cap when it has none, or a looser one over the same period. A tighter cap, or one over another period, is kept |
GET /api/governance/mandates/{agent} returns the mandate and its gaps: which of owner, mandate, success_criteria, allowed_systems and budget are missing. Saving needs agents.update and Cedar update on the agent, and is audited as agent.mandate.saved.
Allowed systems
When a mandate names its systems, a call by the agent to any other MCP server is handled by TICKETIQ_AGENT_MANDATE_SYSTEMS:
| Mode | Effect |
|---|---|
audit (default) | The call goes ahead. agent.mandate.outside is recorded, at most once an hour per agent and server |
enforce | The call is refused before it is sent, and the agent is told to ask an owner to add the system |
off | No check |
A mandate with no allowed_systems limits nothing.
Migrating existing agents
Every agent that has no owner is given the admin (TICKETIQ_ADMIN_USER) as its owner, and every agent without a mandate gets one seeded from what it does today: the MCP servers it is configured with and its current cap. Nothing an agent does changes, and every agent passes both checks.
This runs once by itself after an upgrade (agent.mandate.migrated, with the agents changed), and on demand with POST /api/governance/mandates:migrate (agents.update and access.write). A seeded mandate is marked seeded: true and has no purpose or success criteria: its owner should fill them in, and gaps lists them until they do.