Skip to main content
These are the items a Job Session Object carries: every agent step the worker observes becomes one thread item, posted via post_session_thread_item. The content array carries a brief human-readable rendering; metadata carries the structured detail.

General shape

content[].type and metadata.type are in different scopes — content-item shape vs. event shape — and don’t collide. Consumers (renderers, exporters, the future native widget) dispatch on metadata.type. The presence of metadata.type is the distinguishing mark vs. plain user-posted items, which have no metadata.type set.

Item types (per-thread)

text

The agent’s user-facing text output.
A text item carries no metadata beyond type — the full output is content[0].text. If an item exceeds the budget, the generic truncation path excerpts content[0].text and sets metadata.truncated (see the truncation rules below); there is no separate full-text copy for text items.

tool_call

The agent invoked a tool. Posted before the result so live tailing shows the call landing.

tool_result

The tool’s result for the matching invocation_id.
A tool_result carries no tool name — renderers fold a tool_call / tool_result pair by invocation_id and take the name from the tool_call. The brief is → <first output line> (N lines).

thinking

Internal reasoning blocks (Claude Code). The brief content.text shows the first ~120 characters; the full reasoning is in metadata.text.

status

Progress / status pings (e.g. “Compacting context”). Carries a machine-readable token.

turn_end

Marker that the agent has finished its current turn. Useful for renderers to draw a turn separator and for monitoring.
input_tokens is the total input the model processed this turn (cached + uncached); input_tokens_cached is the portion served from the prompt cache. Both adapters (Claude Code and Codex) report the same breakdown.

pending_prompt and pending_prompt_resolved

Used for the interactive-prompt round-trip. See Interactive prompts.

Self-filter

Every item the worker posts carries the worker’s user_id (because BlobHub stamps the calling user on every post). The worker filters out items where user_id == self.user_id when consuming a thread — they are echoes of its own emissions and must not be re-fed to the agent. This has a documented consequence: a human posting from the same user account is also filtered. See Reference.

350 KB truncation

The worker enforces a 350 KB budget (350_000 bytes) on each serialized thread item and truncates large payloads before posting.
After truncation, a posted item looks like:
The local_log field is relative to ~/.blobhub-worker/jobs/. The full untruncated payload is always recoverable from the worker’s local disk.

See also