Agent Office v0.2.1 · POC Get started
Menu: Reference

Reference

Ledger actions

The shape of a ledger entry, how the hash chain and anchors work, and the actions the office records.

The ledger is the office's append-only audit log. Only the office process writes it, and it lives in the office's state directory, which agents' OS users cannot read. Every state-changing action, by a human, an agent or the office itself, writes one entry. See The ledger for the idea and Audit & the ledger for day-to-day use.

Entry shape#

FieldTypeMeaning
seqintegerPosition in the chain, starting at 1, no gaps.
tstimestampWhen the entry was written.
actorprincipalWho acted: human:<email>, agent:<slug> or office.
on_behalf_ofstring or nullWhose authority the action rests on. Reconciler steps use policy@<sha>, the policy commit that caused them; run entries use agent:<slug>; officectl commands use cli:<OS user>.
actiondotted lowercase nameWhat happened, for example run.started.
targetstring or nullWhat it happened to.
dataJSONDetails. Never contains secrets or token values.
prev_hashhexThe previous entry's hash.
hashhexThis entry's hash.

The hash chain#

hash = sha256( prev_hash + "\n" + canonicalJson({ seq, ts, actor, on_behalf_of, action, target, data }) )

The first entry's prev_hash is 64 zeros. Each append happens in one SQLite transaction (BEGIN IMMEDIATE, so concurrent writers line up behind the head), and database triggers reject any UPDATE or DELETE on the ledger table.

Changing, inserting, reordering or deleting any entry breaks the chain from that point. Verification recomputes it and returns ok, checked (entries checked), and on failure brokenAt (the first bad seq) with a reason. It runs on the Audit page (chain status), in the human MCP tool ledger_verify, in officectl doctor, after officectl restore, and as check 6 of officectl verify.

Anchors#

Every ledger.anchor_every_minutes (default 60), if anything new was ledgered, the office appends the current chain head, {"seq", "hash", "ts"}, to ledger/anchors.jsonl in the policy repo. It commits with its forge admin account, which officectl init allows to push directly to the policy repo's main (if that push is rejected it falls back to a pull request it merges itself). It records the anchor in its anchors table and writes a ledger.anchored entry with the commit. ledger_verify and verify check 6 confirm the latest anchor still matches the database.

Anchors put the chain head somewhere outside the office's database, so rewriting history in the database no longer matches what the forge recorded.

Actions#

Every action this release writes, grouped by area. Actor is who appears in actor; "human" means human:<email>, "agent" means agent:<slug>.

Sign-in and people#

ActionActorWhen
auth.loginhumanA human signs in (password, or by accepting an invite).
auth.login_failedofficeA sign-in with bad credentials.
auth.logouthumanA human signs out.
auth.invite_acceptedhumanA human sets a password from an invite link.
human.invitedoffice or humanAn invite link is created (by the reconciler, officectl init / officectl invite, or an admin on the People page). Never the link itself.
human.access.changedofficeThe reconciler adds a human, re-enables one, or changes their roles from access.yaml.
human.disabledofficeA human was removed from access.yaml and is disabled.
token.minted / token.revokedhumanA personal MCP token is created or revoked on /account (data.kind: mcp.human).

Policy and agents (reconciler)#

All written by office with on_behalf_of: policy@<sha>.

ActionWhen
policy.proposedA policy PR is opened (hire, change, suspend/resume, access). Actor: the human or agent who proposed it.
policy.invalidThe policy has validation errors (once per distinct set); valid agents still apply.
policy.appliedA reconcile finished: reason, commit, number of steps, changed agents, error count.
agent.recordedA proposed agent, or a suspended/retired one that was never provisioned, is recorded.
agent.os_user.ensuredThe agent's OS user exists.
agent.forge_user.ensuredThe agent's forge user exists and is in the agents team.
agent.vault.ensuredThe vault repo, access, labels, branch protection and webhook are in place.
agent.claude_md.renderedCLAUDE.md was rendered and committed to the vault (commit and sha256).
agent.grants.appliedRepository grants from forge.read / forge.write applied; stale ones removed.
token.minted / token.revokedThe short-lived token used to clone the vault onto the host.
agent.vault.checked_outThe vault checkout in the agent's home exists.
agent.provisionedFirst full provisioning of a hired agent.
agent.updatedA hired agent's personnel or charter changed and was re-applied.
agent.resumedA suspended or retired agent was set back to hired.
agent.suspended / agent.retiredThe agent was deactivated: forge login disabled, OS user locked, running runs killed (and for retired, vault archived).
agent.removed_from_policyThe agent's files disappeared from the policy; it is suspended.
agent.reconcile_failedProvisioning one agent failed; the others continue.

Runs#

ActionActorWhen
run.queuedwhoever asked (office for mail, scheduled and verify runs; the human for chat and manual runs)A run is queued.
run.refusedofficeA run fails admission, at enqueue or just before it starts. data.reason is one of: agent is <status>, not hired, personnel status is <status>, not hired, no personnel file in the current policy, unknown agent <slug>, trigger "<kind>" not allowed (run.triggers: …), budget exhausted: …, model key missing.
run.startedofficeA run starts: kind, model, credential kind (api_key or subscription), whether it is isolated, budget cap.
run.toolagentThe agent used a tool (from the harness output stream).
run.deniedagentA tool use was denied, by Claude Code's settings (via: harness) or by the office MCP (via: mcp).
run.killedhuman or officeA run is stopped (queued or running). Also when an agent is suspended.
run.finishedofficeA run ends: status, cost, turns, the transcript's sha256, credential kind. Also written as failed: office restarted for runs a crash left running.
token.minted / token.revokedofficeThe run's forge token run-<runId>: user, name and scopes, never the value. Revoked whatever happens.
mcp.agent.<tool>agentEvery office MCP call by an agent, allowed or not, with a safe argument summary.

Mail, chat, approvals#

ActionActorWhen
mail.senthuman or agentA new mail thread is opened (also the automatic notification when an agent's mail gets a reply).
mail.repliedhuman or agentA reply on a thread.
mail.closedagent or humanA thread is closed.
mail.loop_guardofficeA reply notification past 3 hops was delivered without waking the recipient.
chat.senthumanA human sends a chat message (chat page or agent_chat): thread id, run id (or queued_behind when it waits for the thread's live run), length and channel. Never the text.
approval.requestedagentAn agent asks for approval.
approval.decidedhumanA human approves or denies.
capability.window.openedhumanAn approved window opens: capabilities, end time.
capability.window.revokedhumanA human ends an open window early (End now on Needs you): window id, capabilities, the end time it would have had.
forge.pr.openedagentAn agent opened a pull request with forge_open_pr (or got its already-open PR for that branch back): repo, number, head, base, run.
mcp.human.<tool>humanEvery human MCP call, including refused ones.

Artifacts#

ActionActorWhen
artifact.publishedagentThe office committed an artifact the agent published with artifact_publish. Target artifact:<id>; data: agent, run, title, kind, vault path and repo, commit, size and sha256. Never the content.

Office operations#

ActionActorWhen
office.initializedofficeLedger genesis, written by officectl init.
forge.bootstrappedofficeofficectl init set up the forge org, teams and repos.
secret.created / secret.updatedofficeofficectl secrets set stored a value (the name only).
webhook.receivedofficeA signed forge webhook arrived, with what the office did about it.
ledger.anchoredofficeThe chain head was committed to the policy repo.
verify.attemptofficeOne check of officectl verify ran, with its result (token.minted / token.revoked for the tokens it uses).
office.upgradedofficeofficectl upgrade changed the version and ran migrations.
office.restoredofficeofficectl restore restored a backup whose chain verified.

There is no budget-stop action: budgets are enforced at admission (run.refused) and by the per-run cap passed to Claude Code.

Run events are written by the office from the harness's output stream (stream-json), outside the sandbox. The agent cannot write ledger entries directly; entries with an agent as actor are written by the office about what it observed.