Skip to content

Feedback

chronicle.feedback is a pair of submit-only sinks: submit for plain product feedback, report_error for a reproducible failure that should land in the bug pipeline. Both only write — the review surfaces (admin list, status transitions) live in the bridge, not the SDK.

Pick the right one

You have Method Goes to
An impression, a gap, a feature request submit POST /v1/feedback, no fingerprint, no triage
A failing call with a type/message/stack report_error POST /v1/errors, fingerprinted and deduped

A reproducible error is not feedback. If you have a message and a stack, reach for report_error so the failure gets fingerprinted and triaged instead of sitting in a free-form queue.

submit — product feedback

submit files non-bug feedback and returns the created feedback id. body_md is Markdown by contract (tables, fenced code, lists all render); operators read it in the admin bridge.

fid = chronicle.feedback.submit(
    "The dataset API can't express **sharded** provenance across components.",
    category="gap",
    context={"sdk_method": "datasets.upload"},
)

category must be one of the values below — anything else raises ValueError before a request goes out.

category Use for
feedback An impression or UX note (the default)
gap "The surface can't express what I needed"
feature_request An explicit ask

context is identifiers only

Pass findability keys like experiment_id, skill, or sdk_method — never bodies, transcripts, or secrets. source defaults to "sdk"; skills pass "skill".

report_error — bug pipeline

report_error posts a reproducible error and returns None. The endpoint is fire-and-forget (the server replies 202 Accepted and this method discards the body), but HTTP failures still raise the usual APIError subclasses.

chronicle.feedback.report_error(
    error_type="ConflictError",
    message="experiment already committed",
    stack=traceback.format_exc(),
    request_method="POST",
    request_path="/experiments/{id}/git",   # a route template, not a literal path
    response_status=409,
)

The SDK attaches a client-side fingerprint — the SHA-256 of error_type | message | normalized top stack frames — so the same failure reported twice collapses to one identity. The server recomputes its own fingerprint and treats yours as advisory. Prefer a route template for request_path; the server only strips obvious UUID/integer segments as a backstop.