agent.attached
An agent was put in a room: added, moved in, or brought back. Its harness is handed the room’s last lines with it.
Direction: Chips → the log
Sent by: Chips only; refused from a client
Requires a run: no
Schema: agent.attached.json
Fields
Section titled “Fields”Every event also carries the envelope.
| Field | Required | Type | Description |
|---|---|---|---|
v |
yes | 1 |
Protocol major version. |
type |
yes | "agent.attached" |
|
id |
yes | string |
The event’s own id. Stable across a retry of the same event. |
ts |
yes | string |
When it happened, by Chips’ clock. Stamped on the way in; a value the sender writes is replaced. |
workspace_id |
yes | string |
A workspace identifier: ws_ followed by a ULID. |
space_id |
no | string |
The space, when the event belongs to one. |
run_id |
no | string |
The run, when the event belongs to one. |
seq |
no | number |
Assigned by the server on append, monotonic per workspace. Absent on the way in. |
idempotency_key |
no | string |
Required on every client-originated write. Sending the same key twice is a no-op. |
actor |
yes | object | The participant an event is attributed to. |
actor.kind |
yes | "person" | "harness" | "agent" | "system" |
Whether a person, a harness, one of a harness’s agents or Chips itself acted. |
actor.id |
yes | string |
The participant id, or system for Chips. |
actor.harness_id |
no | string |
For an agent: the harness it speaks through, whose budget and runs are the agent’s (ADR 0087). Filled in by Chips. |
agent_id |
yes | string |
The agent, in the room this event’s space_id names. |
by |
no | string |
Who put it there: a person, its harness, or Chips (system). |
moved_from |
no | string |
The room it left for this one, when moved. |
fork_of |
no | string |
The agent.fork this copy answers, when it is a fork’s copy (ADR 0087, Fork). |
made_for |
no | string |
The agent.asked this new agent answers, when a person asked for it (ADR 0108). |
catch_up |
no | object | The room’s last lines before the agent joined, within the budget its harness gave in hello (ADR 0088, point 5). Added as it is sent to the harness; the log does not keep it. |
catch_up.lines |
yes | object[] | Oldest first, the newest that fit the budget. |
catch_up.lines[].seq |
yes | number |
Where in the log it happened. |
catch_up.lines[].at |
yes | string |
When. |
catch_up.lines[].kind |
yes | "said" | "joined" | "left" | "renamed" | "archived" | "unarchived" |
said: a message, addressed to this harness or not. joined and left: somebody came into the room or went. renamed: somebody took a new name, or the room a new title. archived and unarchived: the room was put away or brought back. |
catch_up.lines[].from |
yes | object | Who: the one who said it, came, went or took the new name; for the room’s own lines, who retitled, archived or unarchived it. |
catch_up.lines[].from.id |
yes | string |
Their participant id, or system. |
catch_up.lines[].from.kind |
yes | "person" | "harness" | "agent" | "system" |
|
catch_up.lines[].from.name |
yes | string |
What they go by now. |
catch_up.lines[].from.role |
no | "owner" | "member" | "guest" |
Their standing in this room, when they are in it (SEC-15). |
catch_up.lines[].from.workspace_role |
no | "owner" | "admin" | "member" | "guest" |
A person’s standing in the workspace (SEC-15): the plain form says it after the name, so a guest’s line reads as a guest’s. Absent for an agent or a harness. |
catch_up.lines[].message_id |
no | string |
On said: the message. |
catch_up.lines[].text |
no | string |
On said: the words as they read now, so an edited message reads edited; a deleted one is not a line. Cut with an ellipsis when the one line is longer than the whole budget. |
catch_up.lines[].transcript |
no | string |
On said: what a voice note said, as the server heard it (ADR 0054). |
catch_up.lines[].files |
no | string[] |
On said: the names of the files it carried. |
catch_up.lines[].addressed_to |
no | string[] |
On said: the agents it was for (ADR 0081, ADR 0087), so a harness can leave out a line one of its agents already took a turn on. Absent on a message from before Chips said so. |
catch_up.lines[].held |
no | true |
On said: the guard held it (ADR 0081), so it was for nobody. |
catch_up.lines[].name |
no | string |
On renamed, for a participant: the name they took. |
catch_up.lines[].previous |
no | string |
On renamed, for a participant: the name they went by until then. |
catch_up.lines[].title |
no | string |
On renamed, for the room: its new title. |
catch_up.since_seq |
yes | number |
Where they start: after this seq. With a message, where the turn that said the harness’s own last message in the room began (ADR 0105), else its joining; from the pull route, 0. |
catch_up.truncated |
yes | boolean |
Whether older lines after since_seq were left out to fit the budget. |
catch_up.before |
yes | number |
A cursor: GET /v1/spaces/:id/context?before= this reads what came before these lines. |
catch_up.files |
no | object[] | The room’s files at their current version, newest first, the 20 newest (ADR 0099): with a message, as of it, its own files included; from the pull route, as of now. Each with a URL for this harness. Absent from a Chips before files, and when the room has none. |
catch_up.files[].name |
yes | string |
The file’s name, which its versions share. |
catch_up.files[].version |
yes | number |
Which version this is: 1 for the first, counting each change of its bytes. |
catch_up.files[].attachment_id |
yes | string |
The attachment that is this version: what a post names in replaces when it changes it. |
catch_up.files[].sha256 |
yes | string |
Lowercase hex digest of this version’s bytes. |
catch_up.files[].byte_size |
yes | number |
Size in bytes. |
catch_up.files[].mime_type |
yes | string |
Sniffed from the bytes on upload. |
catch_up.files[].by |
yes | object | Who posted this version, as a line’s from says it. |
catch_up.files[].by.id |
yes | string |
Their participant id. |
catch_up.files[].by.kind |
yes | "person" | "harness" | "agent" | "system" |
|
catch_up.files[].by.name |
yes | string |
What they go by now. |
catch_up.files[].at |
yes | string |
When this version was posted. |
catch_up.files[].message_id |
no | string |
The message that posted this version. |
catch_up.files[].width |
no | number |
Pixels, for a photo or a video. |
catch_up.files[].height |
no | number |
Pixels, for a photo or a video. |
catch_up.files[].duration_ms |
no | number |
Milliseconds, for a sound or a video. |
catch_up.files[].replaces |
no | string |
In one name’s versions (?name=): the version this one was made from, as its post said (message.post.replaces). Absent where the post said nothing, or named no version of this file. |
catch_up.files[].url |
no | string |
For a harness: a signed URL for this version, bound to its token, as a message’s attachments are. Absent for a person, who fetches it by id. |
catch_up.files[].url_expires_at |
no | string |
When url stops working. |
catch_up.spend |
no | object | What the room’s job has spent, as of the message (for one Chips held, as of its hand-over, when a new job began), against what the room allows a job (ADR 0117). With a message only; the room note says it in words. Absent from a Chips before it. |
catch_up.spend.ceiling_usd |
yes | number |
What the room allows a job, in US dollars: its own ceiling, or the default (3) when nobody has set one. |
catch_up.spend.spent_usd |
yes | number |
What the room’s runs reported costing since the job began, in US dollars, every harness’s together. |
catch_up.spend.since_seq |
yes | number |
Where the job began: the seq of the last thing a person did in the room, or of the last brief handed into it, whichever is later; 0 when neither has happened. |
catch_up.spend.uncounted_runs |
yes | number |
How many of the job’s runs reported no cost, and so count nothing. |
Example
Section titled “Example”{ "v": 1, "type": "agent.attached", "id": "evt_01K4ZQPX0000000000000000G3", "ts": "2026-09-30T09:06:00.004Z", "workspace_id": "ws_01K4ZQPX000000000000000001", "actor": { "kind": "person", "id": "usr_01K4ZQPX000000000000000003" }, "agent_id": "agt_01K4ZQPX0000000000000000A1", "space_id": "spc_01K4ZQPX000000000000000002", "by": "usr_01K4ZQPX000000000000000003", "moved_from": "spc_01K4ZQPX0000000000000000S7"}