Events
Goose uses EventFormat::Goose. It is run with goose run --output-format stream-json, which emits a line-delimited JSON stream on standard output: each
non-empty line is a complete JSON object carrying a top-level type. The harness
layer parses that stream and maps each record onto the normalized harness
events.
Raw event stream
Section titled “Raw event stream”The stream is made up of four record types:
| Goose record | Handling |
|---|---|
message | A serialized conversation message whose content is an array of blocks (text, thinking/redactedThinking, toolRequest, toolResponse) processed in order. |
notification | Surfaced verbatim as an unknown event rather than parsed from prose. |
error | Becomes an error event. |
complete | The run boundary. It carries usage (consumed for metrics) and flushes any pending assistant span. |
Within a message, assistant text blocks are agent progress and assistant
thinking blocks are the model’s reasoning; user text is the echoed prompt and is
ignored, and redactedThinking blocks carry no readable text. Goose streams each
fragment as cumulative-or-delta records sharing a message id, so fragments of
the same kind and id are accumulated into one pending span: a record that restates
the pending text replaces it (a cumulative update), and any other same-kind,
same-id record is appended (a delta). A pending span is flushed when activity of a
different kind or id follows, or when the run completes — so a message’s
reasoning is reported just ahead of its
agent message.
A toolRequest block is recorded against its call id and resolved when the
matching toolResponse arrives; the two are correlated by id. The response’s
toolResult.status (success/error) sets the event’s success field. A
toolRequest that cannot be parsed becomes an unknown event.
Normalized mapping
Section titled “Normalized mapping”| Raw | Normalized |
|---|---|
assistant text block | agent (accumulated across same-id fragments, then flushed) |
assistant thinking block | reasoning (accumulated across same-id fragments, then flushed) |
user text, redactedThinking | consumed — no event |
toolRequest + matching toolResponse | the tool event for the tool, or unknown |
complete | consumed for usage; flushes pending text — no event of its own |
error | error |
notification | unknown |
| unrecognized record / block type | unknown |
The harness layer does not capture a session id from Goose’s stream, so harness events from a Goose run carry no session ID.
Tool mapping
Section titled “Tool mapping”Goose and MCP servers prefix tool names with an extension id (such as
developer__shell); the name is split on __ and the extension prefix is
stripped before classification. Tools from the todo extension are consumed as
internal session state. The remaining base names map as follows:
| Goose tool | Event |
|---|---|
read, read_image | read (an image’s path comes from its source field) |
write, edit | write |
text_editor | read or write, by its command (view/read read; write/create/overwrite/edit/str_replace/insert/move/rename/delete write; anything else unknown) |
shell | command, or a recognized file operation |
grep, glob | search |
list, tree | list |
load_skill, skill | skill |
todo__* | consumed — internal session state, no event |
| any other tool | unknown |
See Harness Events for the normalized event contract.