Agent → Worker Dispatch
Agent.process authenticates the message, then hands execution to a fresh
Worker bound to that one message and identity:
// shared/src/createAgent.ts (excerpt)
async process(message: Message) {
// extract the identity token from the message's "from" field
const token = message.from.slice(28)
let identity: TokenIdentity | null = null
// identity is anonymous unless a decryptable token is present
if (token && token !== "anonymous" && this.encryptionKey) {
const decrypted = await decrypt(token, this.encryptionKey)
identity = JSON.parse(decrypted) as TokenIdentity
// honor the host-provided revocation check, if any
if (this.isTokenRevoked && (await this.isTokenRevoked(token))) {
identity = null
}
}
const worker = new Worker({ agent: this, message, identity })
return await worker.process()
}
The agent is the router and registry; the worker is the sandbox that actually runs handlers and enforces the rules.
do vs system
The worker exposes two ways to run an operation — and the difference is the system’s whole security model:
do(op, data)— permission-checked against the injected capability map. This is how the incoming message’s operation runs.system(op, data)— privileged, for operation-to-operation calls. The composition itself is the trusted, audited path.
// shared/src/createWorker.ts (excerpt)
async do(operation, data) {
// check if the identity is allowed to run the operation
if (!this.agent.can(this.identity, operation))
throw Error(`access denied: ${operation}`)
return this.processTask(operation, data, false)
}
async system(operation, data) {
// run the task as system (bypasses access checks)
return this.processTask(operation, data, true)
}
Every task then passes through the same pipeline — existence check, recursion guard, input parse, handler, output parse:
// shared/src/createWorker.ts (excerpt)
// prevent infinite loops, cannot call an operation recursively
if (isSelfOrParent(this.stack, operation))
throw Error(`cannot call "${operation}" recursively`)
this.stack.push([operation, data, asSystem])
queueMicrotask(() => this.stack.pop())
// validate input
const input = task.input ? task.input.parse(data) : undefined
// process operation
const result = await task.default(this, input)
// validate output
const output = task.output ? task.output.parse(result) : undefined
Composition: Register as Orchestration
accounts/register is the showcase. It is callable by an anonymous user,
yet it orchestrates three operations an anonymous user could never call
directly — because the composition runs as system:
// server/src/services/accounts/register.ts (excerpt)
// create the account record
const account = await io.system("accounts/create", {
type: "MEMBER",
status: "ACTIVE",
})
// create the secret identity record
await io.system("identities/create", {
type: "SECRET",
identifier: data.identifier,
token: data.secret,
accountId: account.id,
})
// issue an identity token by connecting
const { token, role } = await io.system("accounts/connect", {
identifier: data.identifier,
secret: data.secret,
})
return { token, role }
Three mechanisms make this safe:
- The permission boundary sits at the edge — only the entry operation is capability-checked; internal calls are trusted by design.
io.isSystemlets operations relax ownership checks when invoked internally —books/addrequires catalog ownership from users, but skips it during a system bulk import.- The recursion guard rejects an operation that re-enters itself or its parent, so a buggy composition fails loudly instead of looping forever.
This is a tiny in-process command bus: capability check at the edge, trusted composition underneath, uniform validation everywhere.