Skip to content

Office link

Proposed (decision 0016). Link version: 2. The office link connects an office to a monitoring or management service, for example a dashboard. The office connects out to the service; the service never connects to an office. The service keeps no office data: it asks the office over this connection, so an office that is offline shows nothing. The messages are defined as schemas in the @outstaff/protocol package.

  • The office opens a WebSocket to link.url from the team file, with the headers Authorization: Bearer <OUTSTAFF_LINK_TOKEN> and Outstaff-Link-Version: 2. A service that does not accept the token refuses the upgrade (HTTP 401 or 403).
  • Messages are JSON text frames: { "type": "request", "payload": { ... } }. A frame that does not parse is ignored; a request that does not, when its id can be read, gets an invalid error.
  • The service sends welcome first. With another version the office closes the connection with code 4426. After the welcome the office sends people, then notifications as things change, and answers requests.
  • Either side sends ping when it has been quiet; the other answers pong. The office closes a connection that stays silent for three of its ping intervals.
  • When the connection drops or is refused, the office tries again with a backoff that doubles up to a cap. The link never holds up the office.

The service sends request with an id, a method and its params; the office answers one response with that id and either result or error. Requests are answered in any order. A request the office cannot answer in time gets timeout. Times are ISO-8601 UTC; cursors are times, never ids.

Error codes: unknown_method, invalid, not_found, timeout, failed.

The people snapshot: each person, connected or not, with the item it works on and its queue in run order, each with why it is queued.

Params:

No fields.

Result:

Field Type Required Description
at string yes ISO-8601 time, UTC.
people list of objects yes
people[].handle string yes
people[].name string yes
people[].role string yes
people[].runtime string yes The runtime adapter the person is configured with, for example claude: their own runtime, else the team’s integrations.runtime.
people[].model string yes The model the person is configured with: their model from team.yaml, which every person has.
people[].connected boolean yes Whether the person’s agent is connected to the office now.
people[].counts object yes How much work the person has.
people[].counts.queued integer yes Items waiting to run.
people[].counts.running integer yes Items running now.
people[].current object (id, kind, title, subject, startedAt, runtime, model, lastHeartbeat) or null yes The item the agent is working on; null when idle.
people[].queue list of objects yes Queued items, in the order they run.
people[].queue[].id string yes Id of the work item.
people[].queue[].kind string yes What the item is, for example assigned or review_feedback.
people[].queue[].title string yes
people[].queue[].subject object (type, ref) or null yes What the item is about: a ticket key, a pull request (host/owner/name#n) or a document id.
people[].queue[].priority integer yes Lower runs first.
people[].queue[].trigger human or agent or automation or schedule yes
people[].queue[].reason string yes Why the item is queued, in words.
people[].queue[].scheduledBy object (policy, eventId) or null yes The policy and event that queued it, when the event pipeline did; null otherwise.

Traces of the events the pipeline judged, newest first, filtered on the office, with the total that match. Page with before = nextBefore.

Params:

Field Type Required Description
since string no Only events after this time.
before string no Only events before this time: the cursor for the next page.
limit integer no How many, at most. Default 50.
source string no Only events from this source, for example vcs or tracker.
person string no Only events this person caused, or that wake or act as them.
ticket string no Only events about this ticket.
pr string no Only events about this pull request: owner/name#number.

Result:

Field Type Required Description
events list of objects yes Newest first.
events[].event object yes
events[].event.id string yes <source>:<external id>; the id ost explain takes.
events[].event.source vcs or tracker or knowledge or chat or office yes Where the event came from: the code host, the tracker, the knowledge base, chat, or the office itself.
events[].event.type string yes
events[].event.at string yes When the event happened.
events[].event.subject object yes
events[].event.subject.ticket string no
events[].event.subject.pr object no
events[].event.subject.pr.repo object yes
events[].event.subject.pr.repo.host string yes
events[].event.subject.pr.repo.owner string yes
events[].event.subject.pr.repo.name string yes
events[].event.subject.pr.number integer yes
events[].event.subject.doc string no
events[].event.subject.chat object no
events[].event.subject.chat.channel string yes
events[].event.subject.chat.thread string no
events[].event.actor object yes
events[].event.actor.kind human or agent or automation yes
events[].event.actor.id string yes
events[].event.data object yes Event data as intake normalized it: a ticket move has canonical statuses in from and to and the tracker’s names in fromName and toName.
events[].urls object yes Links to the event’s subject, where the office can resolve them.
events[].urls.ticket string no
events[].urls.pr string no
events[].urls.doc string no
events[].urls.chat string no
events[].policies list of objects yes Every policy, built-in then custom, in order.
events[].policies[].policy string yes
events[].policies[].matched boolean yes
events[].policies[].reason string yes Why it matched or did not.
events[].policies[].failed any no For a policy that listened but did not match: the condition that failed.
events[].policies[].proposals list of any yes What it proposed, when it matched.
events[].aggregation list of objects yes What the aggregation made of each proposal, in order.
events[].aggregation[].policy string yes
events[].aggregation[].proposal integer yes The proposal’s index in its policy’s proposals.
events[].aggregation[].outcome kept or merged or suppressed or rejected or dropped or error yes kept as a decision, merged into another wake of the same person and subject, suppressed by another policy, rejected by an invariant, dropped as pointless or by a conflict it lost, error when the policy threw.
events[].aggregation[].reason string no
events[].aggregation[].decision integer no The index in decisions of the decision it became or was merged into.
events[].decisions list of any yes What the office does: the aggregation’s result.
events[].results object no Each act’s progress, by act id (<event id>:<policy>): the agent it is for makes the changes, so an act for an offline agent waits until it connects.
total integer yes How many events match the filters, however many this page holds.
nextBefore string no Pass as before for the next page; absent when there are no more events.

One event’s trace, by event id. not_found when the office has none.

Params:

Field Type Required Description
id string yes The event’s id, as in its trace.

Result:

Field Type Required Description
trace object yes
trace.event object yes
trace.event.id string yes <source>:<external id>; the id ost explain takes.
trace.event.source vcs or tracker or knowledge or chat or office yes Where the event came from: the code host, the tracker, the knowledge base, chat, or the office itself.
trace.event.type string yes
trace.event.at string yes When the event happened.
trace.event.subject object yes
trace.event.subject.ticket string no
trace.event.subject.pr object no
trace.event.subject.pr.repo object yes
trace.event.subject.pr.repo.host string yes
trace.event.subject.pr.repo.owner string yes
trace.event.subject.pr.repo.name string yes
trace.event.subject.pr.number integer yes
trace.event.subject.doc string no
trace.event.subject.chat object no
trace.event.subject.chat.channel string yes
trace.event.subject.chat.thread string no
trace.event.actor object yes
trace.event.actor.kind human or agent or automation yes
trace.event.actor.id string yes
trace.event.data object yes Event data as intake normalized it: a ticket move has canonical statuses in from and to and the tracker’s names in fromName and toName.
trace.urls object yes Links to the event’s subject, where the office can resolve them.
trace.urls.ticket string no
trace.urls.pr string no
trace.urls.doc string no
trace.urls.chat string no
trace.policies list of objects yes Every policy, built-in then custom, in order.
trace.policies[].policy string yes
trace.policies[].matched boolean yes
trace.policies[].reason string yes Why it matched or did not.
trace.policies[].failed any no For a policy that listened but did not match: the condition that failed.
trace.policies[].proposals list of any yes What it proposed, when it matched.
trace.aggregation list of objects yes What the aggregation made of each proposal, in order.
trace.aggregation[].policy string yes
trace.aggregation[].proposal integer yes The proposal’s index in its policy’s proposals.
trace.aggregation[].outcome kept or merged or suppressed or rejected or dropped or error yes kept as a decision, merged into another wake of the same person and subject, suppressed by another policy, rejected by an invariant, dropped as pointless or by a conflict it lost, error when the policy threw.
trace.aggregation[].reason string no
trace.aggregation[].decision integer no The index in decisions of the decision it became or was merged into.
trace.decisions list of any yes What the office does: the aggregation’s result.
trace.results object no Each act’s progress, by act id (<event id>:<policy>): the agent it is for makes the changes, so an act for an offline agent waits until it connects.

Work items, newest first by when they were created, optionally of one status or person, with the total that match. Page with before = nextBefore.

Params:

Field Type Required Description
status queued or active or waiting or done or blocked or canceled no Only items with this status.
person string no Only this person’s items.
before string no Only items created before this time: the cursor for the next page.
limit integer no How many, at most. Default 50.

Result:

Field Type Required Description
items list of objects yes Newest first, by when they were created.
items[].id string yes Id of the work item.
items[].kind string yes What the item is, for example assigned or review_feedback.
items[].title string yes
items[].subject object (type, ref) or null yes What the item is about: a ticket key, a pull request (host/owner/name#n) or a document id.
items[].person string yes
items[].status queued or active or waiting or done or blocked or canceled yes
items[].priority integer yes
items[].trigger human or agent or automation or schedule yes
items[].createdAt string yes ISO-8601 time, UTC.
items[].updatedAt string yes ISO-8601 time, UTC.
items[].scheduledBy object (policy, eventId) or null yes The policy and event that queued it, when the event pipeline did.
total integer yes How many items match the filters, however many this page holds.
nextBefore string no Pass as before for the next page; absent when there are no more items.

One work item with its runs, the end of its journal and the traces of the events that queued or joined it. not_found when there is no such item.

Params:

Field Type Required Description
id string yes The work item’s id.

Result:

Field Type Required Description
item object yes
item.id string yes Id of the work item.
item.kind string yes What the item is, for example assigned or review_feedback.
item.title string yes
item.subject object (type, ref) or null yes What the item is about: a ticket key, a pull request (host/owner/name#n) or a document id.
item.person string yes
item.status queued or active or waiting or done or blocked or canceled yes
item.priority integer yes
item.trigger human or agent or automation or schedule yes
item.createdAt string yes ISO-8601 time, UTC.
item.updatedAt string yes ISO-8601 time, UTC.
item.scheduledBy object (policy, eventId) or null yes The policy and event that queued it, when the event pipeline did.
item.runs list of objects yes Every run, oldest first.
item.runs[].startedAt string yes ISO-8601 time, UTC.
item.runs[].finishedAt string or null yes
item.runs[].outcome string or null yes How the run ended, for example done or blocked.
item.runs[].error string or null yes
item.runs[].runtime string or null yes The runtime adapter that ran it, for example claude; null until the agent said.
item.runs[].model string or null yes The model that ran it: the concrete id the runtime reported, else the one the person is configured with; null when neither is known.
item.runs[].usage object (totals, models) or null yes The tokens and API-equivalent cost of the run; null when the agent reported none (an unfinished run, or one that ended without the agent).
item.journal object yes The item’s journal, in short.
item.journal.entries integer yes How many entries the journal has.
item.journal.latest list of objects yes The latest few entries, oldest first; long ones are cut.
item.journal.latest[].at string yes ISO-8601 time, UTC.
item.journal.latest[].author string yes
item.journal.latest[].text string yes
traces list of objects yes The events whose wakes queued or joined the item, oldest first.
traces[].event object yes
traces[].event.id string yes <source>:<external id>; the id ost explain takes.
traces[].event.source vcs or tracker or knowledge or chat or office yes Where the event came from: the code host, the tracker, the knowledge base, chat, or the office itself.
traces[].event.type string yes
traces[].event.at string yes When the event happened.
traces[].event.subject object yes
traces[].event.subject.ticket string no
traces[].event.subject.pr object no
traces[].event.subject.pr.repo object yes
traces[].event.subject.pr.repo.host string yes
traces[].event.subject.pr.repo.owner string yes
traces[].event.subject.pr.repo.name string yes
traces[].event.subject.pr.number integer yes
traces[].event.subject.doc string no
traces[].event.subject.chat object no
traces[].event.subject.chat.channel string yes
traces[].event.subject.chat.thread string no
traces[].event.actor object yes
traces[].event.actor.kind human or agent or automation yes
traces[].event.actor.id string yes
traces[].event.data object yes Event data as intake normalized it: a ticket move has canonical statuses in from and to and the tracker’s names in fromName and toName.
traces[].urls object yes Links to the event’s subject, where the office can resolve them.
traces[].urls.ticket string no
traces[].urls.pr string no
traces[].urls.doc string no
traces[].urls.chat string no
traces[].policies list of objects yes Every policy, built-in then custom, in order.
traces[].policies[].policy string yes
traces[].policies[].matched boolean yes
traces[].policies[].reason string yes Why it matched or did not.
traces[].policies[].failed any no For a policy that listened but did not match: the condition that failed.
traces[].policies[].proposals list of any yes What it proposed, when it matched.
traces[].aggregation list of objects yes What the aggregation made of each proposal, in order.
traces[].aggregation[].policy string yes
traces[].aggregation[].proposal integer yes The proposal’s index in its policy’s proposals.
traces[].aggregation[].outcome kept or merged or suppressed or rejected or dropped or error yes kept as a decision, merged into another wake of the same person and subject, suppressed by another policy, rejected by an invariant, dropped as pointless or by a conflict it lost, error when the policy threw.
traces[].aggregation[].reason string no
traces[].aggregation[].decision integer no The index in decisions of the decision it became or was merged into.
traces[].decisions list of any yes What the office does: the aggregation’s result.
traces[].results object no Each act’s progress, by act id (<event id>:<policy>): the agent it is for makes the changes, so an act for an offline agent waits until it connects.

How much happened in each of the last few windows of time (default the last hour and the last day): events that happened and work items created. Exact, since the office counts them in its store.

Params:

Field Type Required Description
windows list of integer no Window lengths in seconds, each counted back from now. Default one hour and one day.

Result:

Field Type Required Description
at string yes The office’s time of the count; each window ends here.
windows list of objects yes In the order requested.
windows[].seconds integer yes The window’s length, as requested.
windows[].since string yes Where the window starts: at minus seconds.
windows[].events integer yes Events that happened in the window.
windows[].items integer yes Work items created in the window.

Tokens and API-equivalent cost of agent runs that finished in a window (default all of them): per person, with the part of each person’s runs that names no ticket (unattributed), and per day. The cost is what the tokens cost at API list prices, not what a subscription bills.

Params:

Field Type Required Description
since string no Count runs that finished at or after this time.
until string no Count runs that finished before this time. Default now.

Result:

Field Type Required Description
since string or null yes As asked; null for since the start.
until string yes ISO-8601 time, UTC.
byPerson list of objects yes Each person with runs in the window, largest cost first.
byPerson[].person string yes
byPerson[].totals object yes Every run of the person.
byPerson[].totals.inputTokens integer yes
byPerson[].totals.outputTokens integer yes
byPerson[].totals.cacheReadTokens integer yes
byPerson[].totals.cacheCreationTokens integer yes
byPerson[].totals.tokens integer yes All four token counts added up.
byPerson[].totals.costUsd number yes What the tokens cost at API list prices, in USD. API-equivalent: on a subscription it is not what is billed.
byPerson[].totals.runs integer yes Runs counted.
byPerson[].unattributed object yes The person’s runs of work items that name no ticket, for example a chat that filed nothing.
byPerson[].unattributed.inputTokens integer yes
byPerson[].unattributed.outputTokens integer yes
byPerson[].unattributed.cacheReadTokens integer yes
byPerson[].unattributed.cacheCreationTokens integer yes
byPerson[].unattributed.tokens integer yes All four token counts added up.
byPerson[].unattributed.costUsd number yes What the tokens cost at API list prices, in USD. API-equivalent: on a subscription it is not what is billed.
byPerson[].unattributed.runs integer yes Runs counted.
byDay list of objects yes Each day with runs in the window, by when the runs finished, oldest first.
byDay[].day string yes YYYY-MM-DD, UTC.
byDay[].totals object yes
byDay[].totals.inputTokens integer yes
byDay[].totals.outputTokens integer yes
byDay[].totals.cacheReadTokens integer yes
byDay[].totals.cacheCreationTokens integer yes
byDay[].totals.tokens integer yes All four token counts added up.
byDay[].totals.costUsd number yes What the tokens cost at API list prices, in USD. API-equivalent: on a subscription it is not what is billed.
byDay[].totals.runs integer yes Runs counted.

One ticket’s tokens and API-equivalent cost: its own runs (the runs of every work item whose subject or references name it) by person, model and kind of round, and its total with its sub-tickets rolled up, as the tracker says which they are.

Params:

Field Type Required Description
ticket string yes Key of the ticket.

Result:

Field Type Required Description
ticket string yes Key of the ticket.
own object yes Every run of every work item whose subject or references name the ticket: its own rounds, reviews and merges of its pull requests, comment rounds and chat sessions attached to it.
own.inputTokens integer yes
own.outputTokens integer yes
own.cacheReadTokens integer yes
own.cacheCreationTokens integer yes
own.tokens integer yes All four token counts added up.
own.costUsd number yes What the tokens cost at API list prices, in USD. API-equivalent: on a subscription it is not what is billed.
own.runs integer yes Runs counted.
total object yes The ticket’s own usage plus its sub-tickets’ totals.
total.inputTokens integer yes
total.outputTokens integer yes
total.cacheReadTokens integer yes
total.cacheCreationTokens integer yes
total.tokens integer yes All four token counts added up.
total.costUsd number yes What the tokens cost at API list prices, in USD. API-equivalent: on a subscription it is not what is billed.
total.runs integer yes Runs counted.
subTickets list of objects yes The sub-tickets rolled into total, each with its own total.
subTickets[].ticket string yes
subTickets[].total object yes
subTickets[].total.inputTokens integer yes
subTickets[].total.outputTokens integer yes
subTickets[].total.cacheReadTokens integer yes
subTickets[].total.cacheCreationTokens integer yes
subTickets[].total.tokens integer yes All four token counts added up.
subTickets[].total.costUsd number yes What the tokens cost at API list prices, in USD. API-equivalent: on a subscription it is not what is billed.
subTickets[].total.runs integer yes Runs counted.
byPerson list of objects yes The ticket’s own usage per person, largest cost first.
byPerson[].key string yes The person’s handle, the model id, or the kind of round.
byPerson[].totals object yes
byPerson[].totals.inputTokens integer yes
byPerson[].totals.outputTokens integer yes
byPerson[].totals.cacheReadTokens integer yes
byPerson[].totals.cacheCreationTokens integer yes
byPerson[].totals.tokens integer yes All four token counts added up.
byPerson[].totals.costUsd number yes What the tokens cost at API list prices, in USD. API-equivalent: on a subscription it is not what is billed.
byPerson[].totals.runs integer yes Runs counted.
byModel list of objects yes The ticket’s own usage per model id, largest cost first.
byModel[].key string yes The person’s handle, the model id, or the kind of round.
byModel[].totals object yes
byModel[].totals.inputTokens integer yes
byModel[].totals.outputTokens integer yes
byModel[].totals.cacheReadTokens integer yes
byModel[].totals.cacheCreationTokens integer yes
byModel[].totals.tokens integer yes All four token counts added up.
byModel[].totals.costUsd number yes What the tokens cost at API list prices, in USD. API-equivalent: on a subscription it is not what is billed.
byModel[].totals.runs integer yes Runs counted.
byKind list of objects yes The ticket’s own usage per kind of round (the work item’s kind, for example assigned or review_feedback), largest cost first.
byKind[].key string yes The person’s handle, the model id, or the kind of round.
byKind[].totals object yes
byKind[].totals.inputTokens integer yes
byKind[].totals.outputTokens integer yes
byKind[].totals.cacheReadTokens integer yes
byKind[].totals.cacheCreationTokens integer yes
byKind[].totals.tokens integer yes All four token counts added up.
byKind[].totals.costUsd number yes What the tokens cost at API list prices, in USD. API-equivalent: on a subscription it is not what is billed.
byKind[].totals.runs integer yes Runs counted.

The doctor checks: the ones the office runs at start, every day at office.doctor.daily_at, on demand and, while one fails or warns, every office.doctor.retry_minutes, and the ones each agent reports when it starts. A failing check stays failing until a later run passes.

Params:

Field Type Required Description
run boolean no Run the office’s checks now and answer with the result. A run that outlasts the request is answered with timeout; the health notification carries its result.

Result:

Field Type Required Description
at string yes ISO-8601 time, UTC.
summary object yes How many checks have each status.
summary.ok integer yes
summary.warn integer yes
summary.fail integer yes
lastRun string or null yes When the office last ran its own checks; null before the first run ends.
checks list of objects yes Every check, failures first, then warnings, then the rest; by scope and name within each.
checks[].name string yes What is checked, for example Tools install.
checks[].status ok or warn or fail yes
checks[].detail string yes What was found, naming the value that is wrong.
checks[].fix string no What to change, when the check is not ok.
checks[].key string no The secret key the check is about, when it is about one.
checks[].adapter string no The adapter that made the check, if one did.
checks[].scope string yes Whose check it is: office for the checks the office runs, else the handle of the person whose agent reported it.
checks[].firstSeen string yes When the check first reported this status.
checks[].lastSeen string yes When a run last reported the check.

First message after the service accepts the connection: which office this is. The office answers requests and sends notifications only after it.

Sent by: the service.

Field Type Required Description
version integer yes LINK_VERSION the service speaks.
office object yes How the service knows this office.
office.id string yes
office.name string no

Sent right after the welcome: the office’s team, version and pipeline mode.

Sent by: the office.

Field Type Required Description
office object yes Which office this is.
office.team string yes The team’s name from its team file.
office.version string yes The office’s version.

Asks the office for data; see Methods. Answered by one response with the same id.

Sent by: the service.

The fields depend on the method; see Methods.

The answer to a request: its result, or an error.

Sent by: the office.

The fields depend on the method; see Methods.

Every person with the item it works on and its queue, as the people method gives it. Sent when the welcome comes and whenever it changes, at most about once a second.

Sent by: the office.

Field Type Required Description
at string yes ISO-8601 time, UTC.
people list of objects yes
people[].handle string yes
people[].name string yes
people[].role string yes
people[].runtime string yes The runtime adapter the person is configured with, for example claude: their own runtime, else the team’s integrations.runtime.
people[].model string yes The model the person is configured with: their model from team.yaml, which every person has.
people[].connected boolean yes Whether the person’s agent is connected to the office now.
people[].counts object yes How much work the person has.
people[].counts.queued integer yes Items waiting to run.
people[].counts.running integer yes Items running now.
people[].current object (id, kind, title, subject, startedAt, runtime, model, lastHeartbeat) or null yes The item the agent is working on; null when idle.
people[].queue list of objects yes Queued items, in the order they run.
people[].queue[].id string yes Id of the work item.
people[].queue[].kind string yes What the item is, for example assigned or review_feedback.
people[].queue[].title string yes
people[].queue[].subject object (type, ref) or null yes What the item is about: a ticket key, a pull request (host/owner/name#n) or a document id.
people[].queue[].priority integer yes Lower runs first.
people[].queue[].trigger human or agent or automation or schedule yes
people[].queue[].reason string yes Why the item is queued, in words.
people[].queue[].scheduledBy object (policy, eventId) or null yes The policy and event that queued it, when the event pipeline did; null otherwise.

An event the pipeline judged, as soon as the office records its trace.

Sent by: the office.

Field Type Required Description
recordedAt string yes When the office recorded it. A trace is sent again when an act’s result is added.
trace object yes
trace.event object yes
trace.event.id string yes <source>:<external id>; the id ost explain takes.
trace.event.source vcs or tracker or knowledge or chat or office yes Where the event came from: the code host, the tracker, the knowledge base, chat, or the office itself.
trace.event.type string yes
trace.event.at string yes When the event happened.
trace.event.subject object yes
trace.event.subject.ticket string no
trace.event.subject.pr object no
trace.event.subject.pr.repo object yes
trace.event.subject.pr.repo.host string yes
trace.event.subject.pr.repo.owner string yes
trace.event.subject.pr.repo.name string yes
trace.event.subject.pr.number integer yes
trace.event.subject.doc string no
trace.event.subject.chat object no
trace.event.subject.chat.channel string yes
trace.event.subject.chat.thread string no
trace.event.actor object yes
trace.event.actor.kind human or agent or automation yes
trace.event.actor.id string yes
trace.event.data object yes Event data as intake normalized it: a ticket move has canonical statuses in from and to and the tracker’s names in fromName and toName.
trace.urls object yes Links to the event’s subject, where the office can resolve them.
trace.urls.ticket string no
trace.urls.pr string no
trace.urls.doc string no
trace.urls.chat string no
trace.policies list of objects yes Every policy, built-in then custom, in order.
trace.policies[].policy string yes
trace.policies[].matched boolean yes
trace.policies[].reason string yes Why it matched or did not.
trace.policies[].failed any no For a policy that listened but did not match: the condition that failed.
trace.policies[].proposals list of any yes What it proposed, when it matched.
trace.aggregation list of objects yes What the aggregation made of each proposal, in order.
trace.aggregation[].policy string yes
trace.aggregation[].proposal integer yes The proposal’s index in its policy’s proposals.
trace.aggregation[].outcome kept or merged or suppressed or rejected or dropped or error yes kept as a decision, merged into another wake of the same person and subject, suppressed by another policy, rejected by an invariant, dropped as pointless or by a conflict it lost, error when the policy threw.
trace.aggregation[].reason string no
trace.aggregation[].decision integer no The index in decisions of the decision it became or was merged into.
trace.decisions list of any yes What the office does: the aggregation’s result.
trace.results object no Each act’s progress, by act id (<event id>:<policy>): the agent it is for makes the changes, so an act for an offline agent waits until it connects.

A work item was queued or its status changed, with what a list of items shows (title, subject, kind, person, status), so a service can patch its list without asking.

Sent by: the office.

Field Type Required Description
id string yes
person string yes
kind string yes
title string yes
subject object (type, ref) or null yes What the item is about: a ticket key, a pull request (host/owner/name#n) or a document id.
status queued or active or waiting or done or blocked or canceled yes
updatedAt string yes ISO-8601 time, UTC.

The doctor checks, as the health method gives them. Sent when the welcome comes and whenever a check is added, removed or changes, not when a run only confirms them.

Sent by: the office.

Field Type Required Description
at string yes ISO-8601 time, UTC.
summary object yes How many checks have each status.
summary.ok integer yes
summary.warn integer yes
summary.fail integer yes
lastRun string or null yes When the office last ran its own checks; null before the first run ends.
checks list of objects yes Every check, failures first, then warnings, then the rest; by scope and name within each.
checks[].name string yes What is checked, for example Tools install.
checks[].status ok or warn or fail yes
checks[].detail string yes What was found, naming the value that is wrong.
checks[].fix string no What to change, when the check is not ok.
checks[].key string no The secret key the check is about, when it is about one.
checks[].adapter string no The adapter that made the check, if one did.
checks[].scope string yes Whose check it is: office for the checks the office runs, else the handle of the person whose agent reported it.
checks[].firstSeen string yes When the check first reported this status.
checks[].lastSeen string yes When a run last reported the check.

Checks that the other side is there; answer with pong.

Sent by: either side.

No fields.

Answers ping.

Sent by: either side.

No fields.