SEARCHABLE RECORD

Flight recorder

Every governed request in a timeline a compliance officer can read, and a search box that never writes SQL.

Token Observe’s flight recorder is the searchable record of every governed request, in a timeline that explains each step in a plain sentence. The tool calls and their arguments, the policy decisions, the approvals, the tokens and the cost are in it; prompt and reply text is not, while conversation capture is left at its metadata default. Search takes a compliance officer’s question in English (refunds over £200 approved by a human last week) and returns a validated filter object, never SQL. It cannot aggregate: no grouping, no correlation across traces.
Search contract
Question in, JSON filter out: fourteen allow-listed fields
Fallback
Deterministic keyword parser when no model answers
Evidence export
SHA-256 over canonical JSON; digest-sealed, not signed
Trace retention
Cloud activity: 30 days. Customer hosting: unset means keep forever
No aggregationThe filter cannot group, count or correlate across traces
the problem

Your logs cannot answer the compliance officer’s question.

An agent estate writes its history into application logs, provider dashboards and whatever the framework printed, and the question a compliance officer arrives with (did any agent move more than £500 without a human looking at it?) is answerable from none of them.

The obvious fix cannot ship: let a model write the query and you have built an interpreter input generated from untrusted text, because the events table holds tool results written by whoever wanted them read.

the mechanism

How it works

Steps 3 and 11 of the request path. The order is encoded in the evaluator, and where each step sits is the reason the guarantee holds.

  1. 01

    The trace opens before anything is decided

    A trace id is minted at step 3 of the request path, before the scanners and the policy verdict, so a request blocked a millisecond later is recorded rather than missing. It comes back on a header on every request, refusals included, and every later read of it is audited.
  2. 02

    A question becomes a filter object

    The model’s only permitted output is minified JSON matching the trace filter schema, validated against fourteen allow-listed keys. An unknown key is a hard failure, and page size and offset are absent from the list, so a filter cannot widen its own page.
  3. 03

    The interpretation is shown back, editable

    The response carries the filter, a plain-English explanation naming every field it set, and whether a model or the keyword parser produced it. Each field renders as an editable chip written into the URL.
one request, one verdict, four ways out

Every check lives in one function, so you can read your rules and know what they do.

one request from a governed agent

POST /v1/chat/completions

The key resolves to one registered agent with a named owner, and the trace is opened before anything can refuse the request.

one evaluator, no input or output of its own

Kill switches, then lifecycle, then deny-by-default permissions across every delegation hop, then rate limits, then your policies by priority.

returns: allow · block · require_approval  —  plus a redaction plan

A spend ceiling is the deliberate exception: it is deferred until routing has fixed which provider and model will serve the call, so it is tested against the price you will pay.

allow
Forwarded as sent

Routed to the provider you configured, on your key. Metering runs last and the trace closes with a terminal status.

200
allow + redaction plan
Forwarded, values masked

The plan is applied to the outbound payload and a redaction event records kinds and counts, never values. A redaction that cannot be applied faithfully becomes a refusal instead.

200
require_approval
Held for a named person

An approval bound to a hash of this exact payload, single-use and expiring. The caller receives the approval id and the header to resume with.

403 ACP_APPROVAL_REQUIRED
block
Refused before egress

429 ACP_BUDGET_EXCEEDED or ACP_RATE_LIMITED where a ceiling decided it. The trace closes as blocked and is kept as thoroughly as one that went through.

403 ACP_POLICY_BLOCKED

Verdict names and status codes are the product’s own. Every rule can run in shadow mode first, where the decision is recorded and the request is not changed. That is how you learn your false-positive rate before you refuse real work.

A question becomes a filter object, never SQL.

The model never emits SQL, table names, column names or operators. Its entire output is a JSON object of known keys and typed values, validated before a query builder emits parameterised SQL, and the call opens no trace of its own because a search must not add rows to the corpus being searched. The cost: misinterpretation replaces injection as the main failure mode.

One question, and everything the translator may return
POST /api/traces/search
{ "query": "refunds over £200 approved by a human last week" }

-- the model's entire output, validated before it is used --
{ "minAmount":   200,
  "hasApproval": true,
  "since":       "2026-08-25T00:00:00.000Z",
  "textQuery":   "refunds" }

-- any other key, or a page size: rejected --
a recorded request, and what was never recorded
The AI conversations and activity screen. Filters for recorded text, team, the person or principal an agent acted for, tool name and outcome sit above a collapsed plain-English investigation search. One recorded request is listed: an evaluation assistant, completed, 78 tokens, $0.0003. The page states that message content exists only where capture was enabled and that hidden model reasoning is not available.

Sample data in the real Token Observe interface, recorded from a local evaluation with a temporary database, a mock provider and one request. No live provider key was used.

What a trace holds, and what it does not.

A default install records the tool arguments and results arriving through the tool gateway, capped at 16,000 characters; the policy decisions; redaction records as kinds and counts, never values; and response metadata.

Whether the model’s answer is stored depends on one setting, so the setting is named every time. Out of the box ACP_CONVERSATION_CAPTURE is metadata and no prompt or reply text is kept at all. Set it to redacted and the prompt as sent and the assistant’s reply are both written as evidence, mask-redacted before truncation and bounded at 32,000 characters and 100 messages. A default trace is not a transcript; a redacted one is evidence of the exchange, not the exchange.

Approvals used to be the one place raw model output was persisted and are not any more: an action summary is the tool or model name plus the policy’s reason, mask-redacted and cut at 240 characters.

the order is the guarantee
  1. beat 01
    Name the caller
    • 1Authenticate
    • 2Resolve the agent

    Nothing is decided for an anonymous caller. The key resolves to one registered agent with a named owner, and its roles, its ceilings and any stop switch in force are read live from the store on every request, not from a cached copy, so a suspension takes effect on the next call instead of after a redeploy.

  2. beat 02
    Start the record, then read what is being sent
    • 3Open the trace
    • 4Sanitise
    • 5Scan

    The trace is opened before anything can refuse the request, which is why a blocked call is recorded as thoroughly as one that went through. Only then is the text normalised and scanned, in that order, so the detectors see what the model will read rather than what a human reviewer can see.

  3. beat 03
    Decide once
    • 6Govern
    • 6bIntersect with the named human
    • 7Enact

    One function returns one verdict: allow, block, or hold it for a named person to approve. Every check lives in that one place rather than scattered along the path, which is what makes it possible to read your rules and know what they do.

  4. beat 04
    Send it, and only then spend the money
    • 8Route
    • 9Call upstream

    Routing fixes which provider and model will serve the call, so where an agent has a USD ceiling it is tested against the price you will pay, not the one the caller typed. Routing is also the last step that can still refuse locally: after it, the request has left your network.

  5. beat 05
    Govern the answer, then count the cost
    • 10Govern the response
    • 11Meter and record

    A tool call the model proposes is judged before it reaches your agent. Metering runs last and on every ending, including the refusals and the streams a client abandoned halfway, because the tokens were spent either way and a partial trace is still evidence.

Step names and their grouping are the product’s own, and the order is encoded in the evaluator rather than drawn for the page.

Team-scoped, digest-sealed, erasable.

Reads are scoped by team, derived from the signed-in account rather than accepted from the request, and the same check runs on the list, the search, the detail page and the export. An export bundles the traces, their events, the approvals that gated them and a chain verification, then seals it with a SHA-256 digest over the canonical JSON: sealed, not signed. Cloud activity retention is configured to 30 days. Customer-hosted retention is unset by default and unset means keep forever, and one subject's traces can be erased on demand, with a dry run first and both the preview and the deletion audited.

Each line closes off an assumption a reader would otherwise carry into a proof of concept.

What this does not do
elsewhere on the site

Where this comes up

The term, defined

A flight recorder, in an agent system, is the durable record of every governed request — what was asked, which checks ran, what was decided, what was called and what it cost — written by the component that enforces the decision rather than by the agent making the request. That authorship is the defining property: a record produced by the process under investigation describes what that process believes it did, while a record produced by the enforcement point survives that process misbehaving.

Does the trace search send my prompts to a model?

No. Only the operator’s question and the current time reach the translation model; it never sees a trace, a result set or the database. The call opens no trace of its own and the question is never logged. With no model configured, nothing leaves the process at all.

Is an evidence export signed?

No. An export is digest-sealed: a SHA-256 over the canonical JSON of the bundle body, recomputed by the recipient to prove no edit after issue. It proves nothing about origin. The bundle embeds a chain verification and names its protection level, because a default install is unkeyed.

How long are traces kept, and can one person’s be erased?

Cloud activity retention is configured to 30 days. Customer-hosted retention is unset by default and unset means keep forever, so a deployment with a storage-limitation duty has to set it. Once set, an hourly pass ages traces out in batches of 250. Erasure is matched on the human principal or the session id, and the audit entry carries a digest of that identifier rather than the identifier. It acts on the live primary only.

Ask about this capability
Ask how this one works, where it sits in the request path, or what it will not do. Answers stay inside what this page claims.

Prefer to ask a person? Write to James

Your next step

Bring us the agent you are least comfortable with.

Create a cloud account and workspace. No card or server installation. Model calls and Google BigQuery scans can incur separate provider charges.