HubPublic

Answer audit

Answer Audit Logs

Record answer-time package context, inference commitments, evidence source_refs, trace bundles, and correction, void, or redaction events.

Answer audit

Record the package and model context behind each application answer

Goal: keep a tenant-scoped audit trail of the answer a user saw, the package context and model-run commitment used at answer time, trace ids, hashes, registered evidence source_refs, and later correction, void, or redaction events.

An answer audit log records one completed answer. The original shell stays append-only, while changes are recorded as correction_appended, voided, or redacted events. Later review can see the original answer and the correction history together. Reference audio/video evidence is registered first in the private workspace media vault, and the answer audit log cites that asset through source_ref. Lookup returns sanitized metadata; runtime media retrieval returns a short-lived stream URL after recording a purpose, and the resulting access event id is bound into the answer audit log. Manual auditor downloads remain separate purpose-bound URLs. Unicode filenames are returned with an ASCII fallback plus an RFC 5987 filename* value so S3 downloads remain safe. rawctx does not claim to transcribe or understand the media by itself.

Each log can carry an application_key, optional idempotency key, external trace/conversation/message ids, actor or session hashes, question and answer text or hashes, semantic references, source references, policy flags, and metadata. Part A's inference_commitment binds the model ref, runtime ids, input/output hashes, and config hash to the same answer_hash. The SDK canonicalizes it as rawctx.inference.commitment.v1. Part B's inference_proof is a prod-off, tenant-policy gated, pluggable layer. In Platform Admin, open the tenant detail page and enable Inference proof enabled; optionally enable EZKL zkML backend and set daily/monthly budgets, per-job cost caps, queued/concurrent limits, artifact size, and retry limits. After budget and backend policy are enabled, a proof can be queued as an async job. Production ezkl_v1 verification is not run inside the API request path; it is handled by the worker path. Small hash-only external proof envelopes can still be submitted with a pre-created job_id to bind back to the Part A commitment and answer hash, but EZKL verification follows the worker policy. It can also carry OTel trace bundles and evidence asset references without forcing rawctx to own the agent runtime. The trust proof binds the Merkle leaf, KMS-signed STH, OpenTimestamps anchor, and Rekor witness receipt into an explicit ANCHORED, BITCOIN_OBSERVED_PENDING_CONFIRMATION, PENDING, or LOCAL_ONLY state.

rawctx
from pathlib import Path

import rawctx

media = rawctx.register_media_evidence_asset(
    filename="support-call.wav",
    mime_type="audio/wav",
    asset_type="audio",
    content=Path("support-call.wav").read_bytes(),
    metadata={"case_id": "case-123"},
    registry="https://api.rawctx.dev",
)

retrieval = rawctx.retrieve_media_evidence(
    media["evidence_asset_id"],
    purpose="answer_generation",
    external_trace_id="req_123",
    external_message_id="msg_456",
    registry="https://api.rawctx.dev",
)
# Stream retrieval["stream_url"] into the agent before it expires.

answer_hash = "sha256:..."
inference_commitment = rawctx.build_inference_commitment(
    model_ref={
        "provider": "openai",
        "model_name": "gpt-4o",
        "model_version": "2026-05-31",
        "weights_digest": None,
        "tokenizer_digest": None,
        "dtype": None,
        "quantization": "none",
    },
    input_hash="sha256:...",
    output_hash=answer_hash,
    config_hash=rawctx.hash_inference_config({"temperature": 0, "top_p": 1}),
    attestation_level="provider_attested",
    runtime={"library_versions": {}, "runtime_ids": {}, "seed": None},
)

log = rawctx.log_answer(
    application_key="analytics_bot",
    environment="production",
    idempotency_key="analytics_bot:req_123:msg_456",
    external_trace_id="req_123",
    external_message_id="msg_456",
    question_text="AOV 1위 채널은?",
    answer_hash=answer_hash,
    inference_commitment=inference_commitment,
    semantic_refs=[
        {
            "package_ref": "@acme/shopify-orders",
            "package_version": "1.2.0",
            "context_hash": "sha256:...",
            "latest_at_answer_time": True,
            "metrics": ["aov"],
            "rules": ["completed_orders_only"],
        }
    ],
    source_refs=[retrieval["source_ref"]],
    evidence_access_event_ids=[retrieval["access_event_id"]],
    policy_flags={
        "approved_definition_only": True,
        "pii_redacted": True,
    },
    registry="https://api.rawctx.dev",
)

assets = rawctx.list_media_evidence_assets(asset_type="audio", registry="https://api.rawctx.dev")
download = rawctx.request_media_evidence_asset_download(
    media["evidence_asset_id"],
    purpose="auditor_media_review",
    registry="https://api.rawctx.dev",
)
# Manual auditor download remains separate from runtime stream retrieval.
supplemental = rawctx.list_answer_evidence_assets(log["id"], registry="https://api.rawctx.dev")
segments = rawctx.list_answer_segments(log["id"], registry="https://api.rawctx.dev")
text_gate = rawctx.retrieve_text_gate_alpha(
    "AOV retail definition evidence",
    application_key="analytics_bot",
    include_hash_only=True,
    registry="https://api.rawctx.dev",
)

otel = rawctx.ingest_otel_trace_bundle(
    application_key="analytics_bot",
    external_trace_id="req_123",
    trace_bundle={"resourceSpans": []},
    semantic_refs=[{"package_ref": "@acme/shopify-orders", "package_version": "1.2.0"}],
    registry="https://api.rawctx.dev",
)

with rawctx.RawctxClient(registry="https://api.rawctx.dev") as client:
    proof = client.proof_answer(log["id"])
    online_verification = client.verify_proof_bundle_online(proof)
    client.append_answer_log_event(
        log["id"],
        event_type="correction_appended",
        reason="Answer used an outdated package version.",
        payload={"corrected_answer": "wholesale입니다."},
    )
    exported = client.export_answer_logs(format="jsonl", application_key="analytics_bot")

Python SDK

Log from the application that produced the answer

Use rawctx.log_answer() for simple integrations. Long-running services and admin workflows can use RawctxClient helpers for create, list, get, append, and export.

create_answer_log()get_answer_log()list_answer_logs()append_answer_log_event()register_media_evidence_asset()list_media_evidence_assets()retrieve_media_evidence()request_media_evidence_asset_download()request_answer_evidence_asset_upload()register_answer_evidence_asset()list_answer_evidence_assets()request_answer_evidence_asset_download()list_answer_segments()ingest_otel_trace_bundle()retrieve_text_gate_alpha()build_inference_commitment()build_inference_proof()hash_inference_config()hash_inference_model_ref()sha256_file()create_inference_proof_job()submit_inference_proof()list_answer_inference_proofs()proof_answer()verify_proof_bundle_online()export_answer_logs()log_answer()

API

Create, search, and export inside the tenant boundary

The backend API is called with a service token or user session. Hub UI wraps the same surface with BFF routes under Settings.

rawctx
POST /api/answer-audit-logs
GET  /api/answer-audit-logs?application_key=analytics_bot&status=recorded
GET  /api/answer-audit-logs/{id}
GET  /api/answer-audit-logs/{id}/ledger/verify
POST /api/answer-audit-logs/{id}/evidence
GET  /api/answer-audit-logs/{id}/evidence
POST /api/answer-audit-logs/{id}/evidence-assets/upload
POST /api/answer-audit-logs/{id}/evidence-assets/register
POST /api/answer-audit-logs/{id}/evidence-assets/{asset_id}/download
GET  /api/evidence-assets
POST /api/evidence-assets
POST /api/evidence-assets/{evidence_asset_id}/retrieve
POST /api/evidence-assets/{evidence_asset_id}/download
GET  /api/answer-audit-logs/{id}/segments
POST /api/answer-audit-logs/{id}/gate-alpha/retrieve
POST /api/answer-audit-logs/{id}/events
POST /api/answer-audit-logs/otel-trace-bundles
POST /api/answer-audit-logs/text-gate-alpha/retrieve
GET  /api/inference-proof-policy
PUT  /api/inference-proof-policy
GET  /api/platform-admin/tenants/{slug}/inference-proof-policy
PATCH /api/platform-admin/tenants/{slug}/inference-proof-policy
POST /api/answer-audit-logs/{id}/inference-proofs/jobs
POST /api/answer-audit-logs/{id}/inference-proofs
GET  /api/answer-audit-logs/{id}/inference-proofs
GET  /api/answer-audit-logs/export?format=jsonl
GET  /api/answer-audit-logs/export?format=csv
GET  /api/trust/sth/latest
GET  /api/trust/proofs/answers/{id}
POST /api/trust/verify
What to capture
  • idempotency_key: prevents duplicate logs when the same request/message is retried.
  • semantic_refs: records the answer-time package ref, exact version, and context hash.
  • inference_commitment: binds the model ref, runtime ids, input/output hashes, and config hash to the answer_hash.
  • external_trace_id: ties the log to an application trace, support ticket, or observability trace.
  • evidence_assets: connect text, audio, or video sources to the answer log, segment metadata, hash, and storage object; original retrieval is recorded as a separate download authorization.
  • inference_proof_policy: gates Part B proof jobs per tenant and limits backend choice, cost, queue depth, and concurrency before work is created.
Privacy controls

Hash-only is the default. Tenant settings can enable raw question_text and answer_text storage. Hashes stay available even when text storage is off, and public evidence responses omit segment text and storage keys until an explicit Text Gate retrieval is authorized. Original audio/video retrieval records the purpose, actor, and asset id in access events and the ledger before returning a short-lived URL. The bearer download URL itself is not stored in the ledger.

answer_audit_store_question_textanswer_audit_store_answer_textanswer_audit_default_retention_days
Part B proof policy

Inference proof enabled is the tenant-level master switch that allows Part B proof jobs to be created. If it is off, new proof jobs are blocked even when EZKL zkML backend is selected. EZKL can run only when it is in the global backend allowlist, allowed by the tenant policy, and the per-job cap is at least the server-side reserved-cost floor. Production API requests do not verify EZKL synchronously; verification is handled by an ECS worker only when proof work is queued.

/admin/tenants/{tenant_slug}Inference proof enabledEZKL zkML backenddaily/monthly cost capsmanual_ecs_task
Trust proof status

The proof bundle on the detail page includes the answer leaf inclusion proof, STH signature, inference commitment proof, anchor receipts, and witness receipts. ANCHORED means a finalized external anchor and the required witness condition are present. BITCOIN_OBSERVED_PENDING_CONFIRMATION means the OpenTimestamps proof contains a Bitcoin block-header attestation, but final confirmation verification is still pending. PENDING means the structure and signatures are verifiable but OpenTimestamps Bitcoin attestation or witness policy completion is still outstanding. LOCAL_ONLY means the record is still a rawctx-local evidence candidate.

rawctx trust statusrawctx trust proof answer <id>rawctx trust verify proof.json --onlineSettings -> Answer audit -> Trust proof
Ledger and trace ingest
  • /ledger/verify checks that the answer-level hash chain is intact.
  • OTel trace bundle ingest is the on-top path for sealing evidence from LangSmith, Langfuse, or another runtime log.
  • Text Gate alpha keeps hash-only logs as the default and retrieves segment text only for an authorized purpose.
  • Original media download is allowed only for registered rawctx storage assets; pending, external-URI, or redacted assets do not receive presigned URLs.
  • S3 download filenames use a header-safe ASCII fallback plus UTF-8 filename* so Korean, spaced, or otherwise non-ASCII names can be retrieved safely.
Where to review

Tenant managers first register reference audio/video in private workspace settings, copy the source_ref, and pass it in source_refs when creating the answer audit log. This media evidence surface is not exposed in Public Hub navigation or public settings routes. Settings -> Answer audit remains the list/detail, JSONL/CSV export, correction, void, redaction, and supplemental evidence surface.