Agents
Roles and orchestration
A role is written like any other concept: search first, then one vinc_ingest call with the node, its properties, and every edge in the same payload. Orchestration is the edges between roles, and the traps a role must know are records attached to it with evidence.
Everything here is the shape the prompt surface reads: roles in tiers, generated shell files, and one gate. Copy the shape; the names are yours. The four roles every space starts with are on Default and community packs.
Write a role
The id is concept:agent-<name> with hyphens, the type is concept, the domain is vinc/agent. Those three are what the MCP prompt surface reads. The roster is vinc/agent and its direct child domains, so vinc/agent/roles works and anything deeper does not; a role filed elsewhere is a concept like any other and never appears as a prompt. The properties go in props. A minimal role:
{
"nodes": [{
"id": "concept:agent-dev-core",
"type": "concept",
"domain": "vinc/agent",
"title": "Agent role: core development",
"tags": ["agent", "execute", "role"],
"props": {
"tier": "execute",
"rung": "strong",
"mission": "One package, one branch, one pull request, one episode.",
"repos": ["Vinc"],
"paths": ["store/", "api/"],
"reads": ["vinc.spec.dataplane", "vinc.canon.repo-workflow"],
"gates": ["scripts/gate_forbidden.py"],
"test_command": "python -m pytest tests",
"never": ["widen scope past the package", "merge"],
"person_only": ["merge", "migration run"],
"writes_graph": ["episode", "record"]
}
}]
}
props is replaced whole on every write. To add one key, read the current value first (the stored field of the write result gives it) and send the merged object; a partial send drops the keys you left out, without a warning. And a role is a concept on purpose: only the six built-in kinds keep props and domain, so a coined agent type would drop every field above.A change ships with a decision
Because props overwrite, the reading list a role had last month is gone the moment you edit it, while that month's episodes still point at the role. So an edit to reads, gates, never or person_only travels in the same payload as a decision:agent-<role>-<change> node with an about edge to the role, and the decision's note carries the value that was replaced. That is the role's history.
Bind the graph to the role
The facts a role must not rediscover are already in the graph as records, attached to the concept they were found on. Attach each one to the role as well, with the sentence that says why:
{
"nodes": [
{ "id": "record:pk-collision-is-dropped-write", "type": "record" },
{ "id": "concept:agent-dev-core", "type": "concept" }
],
"edges": [{
"from": "record:pk-collision-is-dropped-write",
"to": "concept:agent-dev-core",
"type": "relates_to",
"evidence": "a collision is never two rows, so it cannot be measured after the fact"
}]
}
Both ends of an edge travel in the same vinc_ingest call; an edge whose endpoint is missing from the payload is skipped without an error, so read warnings and merged after every write. Reading a role back takes two calls, because neighbours do not return props and the call that does is heavy:
vinc_graph seed_id=concept:agent-dev-core depth=1
vinc_neighbors node=concept:agent-dev-core
Orchestration is edges
A handoff is a prerequisite_of edge from the role that goes first to the one that follows, and each one states a measured reason rather than a preference. Loose pairs use relates_to. A standing decision that constrains a role attaches with prerequisite_of; a decision about the role itself attaches with about. A few handoffs of the kind a software roster states:
- Design before app development, because a skin built on unsynced tokens fails the surface gate.
- Core before account development, because a contract change has to land in the proxy allowlist and both account operation lists in one pass.
- Every execute role before the gate runner, and the gate runner before both reviewers.
- Release before marketing, because release notes follow the tag.
Five tiers keep the roster small: orchestrate, execute, verify, deliver, knowledge. The split that matters is execute against verify. The verify tier never edits, which is why it can run on the cheapest rung and why it does not escalate; it returns the package to its author.
A rung is assigned by the cost of a wrong answer, not the size of the task. A silent defect gets the strongest model; a loud one, a script that errors, gets a cheap one; verification is always cheaper than authoring. Escalation is one rung up.
What a run leaves behind
Every package run writes an episode in the same session, filed in the work's domain with a second about edge to the role. Filing it under the Agent domain instead would put a hole in the engineering timeline exactly where the work went. An episode written later is a reconstruction.