Deuz SDK 2.0 est sorti — stores, guardrails, handoffs et MCP zéro-config. Nouveautés de la 2.0
Deuz SDK
Reference

Observation events

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

Le contenu des pages de documentation est en anglais. La navigation, la recherche et l’interface suivent la langue choisie.

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 (= toolCallId today), 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/failedAux subsystems (image, midjourney); operation strings like image.generate

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.

Sur cette page