- ACCOUNTING_RULE: since the usage store landed, a contended read reports the accounting unavailable instead of serving an older snapshot; integrity_degraded is a field of /api/state only. - task_done review_status and cancel_origin carry review rationale and cancel reason text, so they are content; task_done reason_code can be null; the task_metrics_event tool counts are null for a task without loop evidence; supervisor_loop_stall_end phase is null when the loop published no facts. A test drives the metrics writer's null path. - llm_round meaning: the monotonic clock, a budget pause restarts the measure, a forced final after an unsettled round includes its attempts, failed attempts can be non-anchor rows, first_request_at/first_answer_at. llm_usage no longer claims every call; a coverage gap names skill reviews started from the Skills page. - ROTATION_RULE no longer freezes the rotation size; REPLICA_RULE says a main turn writes one row; the migration-note pointer is §11.3. - Collector example: one Vector test per row (a test condition passes when any output event meets it, so the shared test could not catch a leak on one row), task_received keeps task.id, child_drive replaces the plane label that collided with the passport's planes; the README names the open-file cost of the archive globs and the deletion of a cancelled subagent's drive. - Error-tracker README: the fields before_send keeps, ERROR and CRITICAL records with the SDK's dedupe, and what the defaults probe observed. - PERSISTENCE.md: the supervisor.jsonl row points to the passport. |
||
|---|---|---|
| .. | ||
| plugin.py | ||
| README.md | ||
| SKILL.md | ||
Send errors to a Sentry-compatible tracker
Verified on 2026-10-06 with sentry-sdk 2.71.0 against the Ouroboros source of the pull request that added this example: an isolated server with two pool workers loaded the extension in every process, and a local Sentry-protocol endpoint received the server's and both workers' errors with secrets masked and no frame locals. The results are in that pull request.
Ouroboros sends no telemetry. This example is for a deployment that runs its own error tracker (self-hosted Sentry, GlitchTip, or any service that accepts the Sentry protocol).
What it sends
For each ERROR or CRITICAL record of a process that loaded it (the SDK skips a repeat of an exception it has already sent): the message, the exception type and text, the code locations of the stack (file paths and function names), the logger, the level, the process role and the Ouroboros version. Secret shapes are masked, but task text, file paths and other user content inside a message or an exception are not, and a secret Ouroboros does not recognize passes too. Enabling this example sends that diagnostic content to your tracker; treat the tracker as holding operational data.
How it reaches the errors
Every process Ouroboros configures logs an unexpected failure as a stdlib logging record with its
traceback: a task exception, a worker crash, an unhandled gateway request (HTTP 500), an uncaught thread
exception. The SDK's logging integration turns each ERROR or CRITICAL record into an event. The extension
starts the SDK in the server and in every pool worker, because it has no declared dependencies and no
binary files, so Ouroboros loads it in process.
Install
- Install
sentry-sdkinto Ouroboros's own environment: in Docker, one layer of your image (pip install sentry-sdk). Do not declare it as a skill dependency: a declared dependency moves the extension into a separate process, where it cannot see these records. The packaged desktop app has no supported way to add a package to its interpreter. - Set
SENTRY_DSNin the server's environment; pool workers inherit it. Without it the SDK sends nothing. - Copy this directory to
data/skills/external/error_tracker/, review it (or attest it as the owner), enable it, and restart, so that workers already running load it too.
Why each setting
With the SDK's defaults, a pilot sent a fake API key verbatim twice, in the exception text and in a frame's local variables. It also sent the machine's hostname, the command line and the list of installed modules, and it enabled its integrations for the HTTP and model clients (httpx, openai), which add trace headers to outbound requests. The example turns all of that off:
include_local_variables=Falseandinclude_source_context=False: frame locals and source lines hold prompts, keys and file contents.default_integrations=Falsewith onlyLoggingIntegration,DedupeIntegrationandAtexitIntegration: no automatic instrumentation of HTTP or model clients, andtrace_propagation_targets=[]keeps trace headers off every outbound request.send_default_pii=False,max_request_body_size="never", andserver_nameset to the process role instead of the hostname.before_sendkeeps only the fields in_EVENT_FIELDS(the event's identity and time, level, logger, platform, SDK, process role, release, environment, tags, fingerprint, message and exception), droppingextra(the logging integration copies every key a caller passed asextra=) and everything else, and passes what it keeps throughouroboros.observability.redact_projection, Ouroboros's own secret redaction.
What it does not see
- Failures before the extension loads.
- The desktop launcher.
- Out-of-process extension children.
- The Claudexor daemon and the coding tools it runs.
- An event still queued when a process is killed.
Those stay in the local logs (logs/server.log, the workers' stderr, logs/launcher.log). The record
passport, ouroboros/contracts/record_contract.py,
lists what the JSONL records guarantee.