Deuz SDK 2.4 ist da — versioniertes Gedächtnis und ein Kontext-Compiler, ein Goal-Supervisor und dauerhafter Scheduler, ein lokaler Docker-Runner und dauerhafte Chat-Streams. Neu in 2.4
Deuz SDK
Reference

Observation events

The versioned ObserveEvent protocol — every event type, its identity fields, and the canonical orderings.

Die Dokumentationsseiten selbst sind auf Englisch. Navigation, Suche und UI-Texte folgen der gewählten Sprache.

Every event extends ObserveEventBase:

FieldMeaning
schemaVersionAlways 1
eventId / sequence / timestampUnique id (since 1.6.1 derived as `${executionId}:${sequence}` — the format is not part of the contract) · 0-based monotonic counter per execution leg · deps.clock.now()
runIdLogical run. Durable runs adopt the session runId; sub-agents inherit the parent's
executionIdOne execution leg — a resume keeps runId but gets a fresh executionId
spanId / parentSpanIdTimeline node: run → step → (model | tool | compaction) → sub-agent
agentPath? / stepIndex?Sub-agent chain · loop step counter (continues across durable legs)
metadata? / truncated?App metadata from ObservationOptions · set when limits truncated a payload

Event catalog

EventKey fields
run.startedoperation (stream-chat/generate-text/generate-object/stream-object/embed/embed-many), provider, model, surface, durable, resumed, resumeFromStepId?
run.completedfinishReason, endReason (natural/stop-condition/max-steps/runaway-tool-errors), stoppedBy?, step/model/tool/retry/approval/checkpoint/sub-agent counters, usage (this leg), cumulativeUsage? (durable), costUsd?
run.suspendedreason (approval/client-tool/sub-agent-approval), pendingApprovalCount (0 is legal for pure client-tool breaks), pendingToolCount, checkpointStepId?
run.abortedUser abort is a resolution, never a failure; usage is honest (often zeros mid-stream)
run.failederror: ObservedError, counters, partialUsage?
model.startedEffective per-step model (post-prepareStep), purpose?: 'compaction-summary', maxRetries, responseFormat?, promptCaching?
model.first-contentcontentType (text/reasoning/tool-call), ttftMs — tool-call-first responses clear TTFT as of 1.6
model.retryfailedAttempt, nextAttempt, delayMs, retryAfterMs?, reason (network/rate-limit/overloaded/server-error — timeouts never retry), statusCode?
model.completeddurationMs, ttftMs?, retryCount, finishReason, usage, output/reasoning lengths, toolCallCount
model.failederror — emitted once; the run terminal reports the same failure once more at run level
step.started / step.completedEffective model, message count, estimatedInputTokens? (compaction estimate), per-step durationMs + usage + cumulativeUsage, tool counters, stoppedBy?
tool.startedtoolCallId, toolName, needsApproval, derived executionMode (server/client — provider-executed tools emit no tool events), parallel
tool.completeddurationMs, outputType, outputSize?
tool.failedThe ORIGINAL thrown error (normalized), selfHealed, consecutiveFailureCount
tool.deniedcause (server-denied/response-denied/no-response/client-tool-no-result), reason?
approval.requestedapprovalId (the request's identity-bound id, 2.3), mode (server/client)
approval.resolvedapproved: boolean, source (server/client-response/default-deny), waitDurationMs? (resume legs, from checkpoint age)
checkpoint.savedstepId, checkpointStepIndex (1-based boundary counter), checkpointStatus, save durationMs, cumulative usage
checkpoint.loadedEmitted by the resume entry points BEFORE run.started; checkpointAgeMs?
checkpoint.failedoperation (save/load), runContinued (save failures never kill the run)
compactionOne per APPLIED layer: layer, threshold, contextWindow, tokensBefore/After (calibrated ESTIMATES), messageCountBefore/After, durationMs
compaction.skippedlayer, reason (e.g. a throwing summarizer — never fails the run)
subagent.started/completed/suspended/failedagentName, depth, parentToolCallId, childRunId? (durable store key), child usage (already folded into the parent — never sum twice)
cost.calculatedAsync priceProvider resolution; may arrive after the terminal event
operation.started/completed/failedsubsystem, operation, itemCount?; on completion durationMs, resultCount?, usage?; on failure error. Aux subsystems (image, midjourney, …) use operation strings like image.generate; the 2.4 subsystems name the operation by its span and add attributes? (see 2.4 spans)

2.4 spans

The 2.4 subsystems report each unit of work as an operation.started event followed by operation.completed or operation.failed. The operation is the span name, and createOtelObserver opens a span of that name. ObservedSubsystem gains 'context', 'goal', 'schedule', 'process' and 'stream'; versioned memory reports under the existing 'memory'. Work inside a run leg shares the leg's runId and executionId and hangs under the step or run span; work outside one (a supervisor tick, a scheduler pass, a process runner call) is reported as a leg of its own. Without an observer or tracer, no event is built.

SpanSubsystemReported for
deuz.context.compilecontextA context package compiled for a model step, or compiled again on overflow; a child of the step's span in a native run
deuz.memory.opmemoryA versioned memory remember, extract, revise, retract, forget, reembed or import, and the SQL stores' prunes
deuz.goal.claim, deuz.goal.dispatch, deuz.goal.retrygoalThe supervisor took a goal's lease; started or resumed its run; retried the run after a retryable failure
deuz.goal.cancel_requested, deuz.goal.cancel_appliedgoalA cancel was recorded; it took effect on the goal's run
deuz.goal.drain, deuz.goal.generationgoalThe supervisor drained; a goal moved to a new spec generation
deuz.schedule.deliveryscheduleA schedule occurrence was delivered to a goal inbox, or disposed of
deuz.process.start, deuz.process.poll, deuz.process.cancel, deuz.process.exit, deuz.process.reconcileprocessThe Docker process runner's calls; the Docker sandbox reports deuz.process.start and deuz.process.exit for each run
deuz.stream.batch, deuz.stream.fencedstreamA durable stream batch committed before it is sent; a stale producer's write refused

Each event can carry attributes: scalar values under deuz.<subsystem>.* keys, never content (no memory text, transcript, tool output or retrieved text). operation.started carries what is known up front, and operation.completed or operation.failed adds what the work found out. The OpenTelemetry observer copies them onto the span next to deuz.subsystem and deuz.operation.

SubsystemAttribute keys
contextdeuz.context.selected, .excluded, .tokens, .estimator, .refresh_reason, .fallback, .cache_prefix_changed, .manifest_digest, and per source deuz.context.source.<source>.selected, .excluded and .tokens
memorydeuz.memory.operation, .record_count, .conflict_retries, .embedding_generation
goaldeuz.goal.id, .revision, .spec_generation, .run_id, .attempt
scheduledeuz.schedule.id, .occurrence_id, .disposition, .catch_up, .reason
processdeuz.process.operation_id, .state, .replayed, .exit_code, .truncated, .reconcile_result, .orphans, .matched, .lost, .removed
streamdeuz.stream.batch_frames, .batch_bytes, .commit_ms, .fencing_token

Chat writes, transcript searches and webhook deliveries report no span.

ObservedError

{ name, category, code?, statusCode?, retryable?, provider?, message? } — category derives from stable DeuzError.code strings (authentication/authorization split on 401/403, rate-limit, overloaded, timeout, network, provider, validation, tool, checkpoint, aborted, unknown). message exists only when capture.errorMessages is on, and always passes redaction.

Canonical orderings

Single call:   run.started → model.started → model.first-content → model.completed → run.completed
With retries:  … model.started → model.retry × N → model.first-content → …   (one model.started per call)
Tool loop:     run.started → (step.started → model.* → tool.started → tool.completed → step.completed) × N → run.completed
Suspension:    … approval.requested → step.completed → checkpoint.saved{suspended} → run.suspended
Resume:        checkpoint.loaded → run.started{resumed} → approval.resolved → tool.* (step-less settle) → step.started → …
Abort:         … model.completed{finishReason:'aborted'} → run.aborted   (never model.failed / run.failed)

Parallel tools emit tool.started in batch order and tool.completed in REAL completion order, each with its own spanId under the shared step span.

Auf dieser Seite