Most agent frameworks let agents call each other directly. A planner hands a job to a researcher, the researcher asks a writer for a draft, the writer pings an emailer. It's flexible and quick to build. It works until someone asks the question they will eventually ask: why did the system send that email?
Direct calls leave no trace. The answer has to be reconstructed from logs, if those logs exist, if they were kept, and if someone thought to record the right things. That's not good enough for systems that act on your behalf in the real world. So we wrote Baton: Bounded Authority for Traceable Orchestrated Networks, a vendor-neutral protocol for agent systems where every unit of work is scoped, every interaction is recorded, and every action that touches the outside world is authorised and metered.
A blackboard, not a phone line
In Baton, specialists cannot reach one another. A specialist never holds a reference to another specialist, and the orchestrator is the only party that can create one, which is what makes the rule enforceable. Information crosses from one capability to another in exactly two ways, and both are recorded:
- A blackboard post, which carries data.
- A delegation, which carries a request for a capability.
There is no third channel. Every piece of data that moves between specialists is therefore a durable, attributed, ordered blackboard entry, and every request for help is a recorded delegation. Auditability becomes a consequence of the architecture, not a logging discipline someone has to maintain.
How the blackboard behaves
The blackboard is deliberately strict:
- Append-only. Entries are immutable and never deleted. Correcting a fact means posting a new one; the old one stays in history.
- Ordered. Every post gets a strictly increasing sequence number. Wall-clock time is never used to decide which post is latest, so clock skew can't rewrite history.
- Fail-closed visibility. Each entry lists who may read it. An empty list means nobody but the author, and that's honoured literally.
- Unreadable equals absent. Asking for an entry you may not see gives exactly the same answer as asking for one that doesn't exist, so nothing leaks through error messages.
- One task, one tenant. A blackboard belongs to exactly one task and one tenant. A post under another tenant raises an error rather than being silently dropped.
Need-to-know context
A specialist never receives the full task. It gets a slice: the identity that always travels (task, tenant, the person who asked, the intent and its own capability) plus only the data keys it declared it needs. An undeclared key never appears anywhere in the slice. A CV screener sees the job title and required skills; it never sees your finance data, because it never asked for it and was never given it. Slicing is a containment boundary, not an optimisation.
Provenance you can walk backwards
A subtask can declare which blackboard entries it consumes. Before it runs, the orchestrator checks those entries exist and are readable; if not, the subtask is skipped and a blocking gap is recorded, so the protocol knows something is missing before it spends anything. When the output is published, it records exactly which entries it was derived from. An auditor can start from any conclusion and walk back to the facts it rested on. And if a prerequisite fails, its dependents don't run at all. Running a specialist whose input never arrived produces a confidently wrong answer, which is worse than an unfinished task.
Bounded authority
What a specialist can do is the intersection of the tools its capability declares and the tools the person who asked is actually authorised to use. A tool it didn't declare is refused even if that person could use it. Any tool not explicitly classified is treated as having side effects.
Delegation is checked just as carefully, before anything is created or any resource spent: the requester must be allowed to delegate to the target, the target can't already be in the chain (no cycles), the depth limit can't be exceeded, and the task's spawn ceiling can't be breached. A refused delegation costs nothing.
One budget for the whole team
Token, tool-call, spawn and depth ceilings belong to the task, not to individual specialists. That distinction matters: a per-specialist limit does nothing about a fan-out of twenty specialists that each stay politely under their own. Exceeding a task ceiling fails the task rather than degrading quietly. Every model call is metered against the person who asked, with an idempotency key, so spend is always attributable.
Humans approve side effects, and "no" isn't a failure
A call to any side-effecting tool, sending, paying, writing to a system, pauses the specialist and doesn't execute until a person approves it. That approval might take hours, far longer than any HTTP request or worker lives. So Baton never keeps the loop's position on a call stack. The run is serialised, message history, iteration count and the pending call, and saved with the task. Approve it tomorrow and it resumes from exactly where it stopped, even after a restart.
A denial isn't treated as an error. It's returned to the specialist as the result of the call, so it can revise its approach or finish without that action. Every tool call carries an idempotency key derived from the subtask, capability, tool and arguments, so replaying a task never repeats a side effect.
Output contracts
If a capability declares an output schema, its output is validated before it becomes visible to anyone. A violation goes back to the specialist for correction, a bounded number of times; after that, the run fails and nothing is published. An implementation without a validator must say so. It can't pretend the contract held.
The eleven invariants
- A specialist never holds a reference to another specialist.
- All data between specialists flows through the blackboard.
- Delegation is restricted to declared capabilities, is never cyclic and never exceeds the depth limit.
- Every specialist receives a context slice, never the full envelope.
- Token, tool-call and spawn budgets are shared across the task, not per specialist.
- Side-effecting tools pause for human approval, mid-loop and resumably.
- A specialist's usable tools are its declared set intersected with what the person actually authorised.
- Every model call is metered against the person who asked, with idempotency keys.
- A blackboard belongs to exactly one task and one tenant.
- Output is validated against its declared schema before it becomes visible to anyone.
- Blackboard and run state survive process restarts.
These are enforced in code and covered by a conformance suite of test vectors, not written up as guidance.
No I/O in the core
Baton is a protocol plus a reference implementation, with a hard rule: the core performs no I/O. It has no dependency on any database, HTTP client or model provider. Models, tools, approvals, metering, storage and memory are all interfaces you implement against your own stack, and the library ships in-memory versions that define the expected behaviour precisely and let you test your adapters against it. Minor versions only ever add fields, and readers preserve fields they don't recognise, so you can upgrade one service at a time.
Baton is the governance layer underneath every action Verkko Nexus takes. Read more on the Baton page.