Skip to content

Troubleshooting

Direct interception

The sender reaches the receiver but AIT shows no messages

Confirm that the sender uses the loopback listener printed by ait intercept start, not the original upstream. AIT uses explicit placement; it cannot observe traffic that bypasses its relay or wrapper.

Messages appear but do not pause

Turn Intercept on. If break conditions exist, temporarily remove them or check protocol, direction, operation, route, source/destination, task, context, and artifact values against the message row.

Requests and responses both pause

An enabled session with no break conditions pauses every decoded message. Add a request direction condition when you only want outbound requests.

The edit will not forward

Structured mode requires valid JSON and a protocol shape the transport encoder can preserve. The editor shows the parse/encode error and retains the original. Correct the value or choose Forward original. Use Raw only when exact bounded frame editing is necessary.

The pending queue is full

AIT fails visibly rather than bypassing interception. Decide existing pending messages or stop with an explicit --pending forward|drop policy, then retry.

Stop asks about pending traffic

Paused messages do not expire. Choose whether shutdown forwards each unchanged or drops it. AIT will not decide silently.

The "Original" pane does not match what the sender sent

That is what an armed transform rule looks like. A rule mutates the message before it reaches the gate, so the pane shows sender_original and the rule-applied candidate separately. If only one is shown, the session has no armed rule and the two are the same message.

No rule matches

Check the transcript before checking the target. A rewrite should show a rule_applied value.

ait traffic tail --run RUN_ID --limit 50 --json
ait traffic inspect --run RUN_ID --cursor RECORD_CURSOR --related-limit 20 --json

Every non-matching rule reports a stable miss code rather than silence:

Code Meaning
predicate_mismatch The rule was eligible; a where predicate did not hold.
missing_path The mutation path does not exist in this message.
decoder_ineligible The transport or decoder cannot carry this rule's paths.
shadowed An earlier rule matched first: the engine returns on first match.
disabled The rule is loaded but switched off.
chain_guard A chain.* guard held the rule back.
chain_state_unavailable The chain ledger could not be read for this decision.
chain_reference_unresolved The rule references a rule ID that is not loaded.

shadowed is the one that surprises people. Set priority: on the rule that should win, or reorder the set through PUT /api/v1/intercepts/{session_id}/rules/order. Note what priority does and does not do. It makes shadowing declared, not absent. Two rules matching the same message still produce one winner and one shadowed: priority only decides which. See the Rule-Miss Playbook.

To tune a rule offline against traffic you already captured, replay the rule set over the transcript instead of re-running the attack:

ait intercept transform trace --transcript out.json --rules rules/

MCP stdio does not start or stop

  • confirm the packaged Seam binary, child executable and cwd exist;
  • use an argument array rather than a shell string;
  • confirm every env_refs source variable exists;
  • raise bounds only after inspecting bounded stderr;
  • on cancellation, inspect the job and transcript summary rather than relaunching immediately.

MCP or A2A correlation is lost

Separate handshake and session failures from rule misses. Verify JSON-RPC request IDs, MCP protocol/session headers, and A2A context/task/artifact identifiers. A rule miss reports a miss code; a transport failure does not, and surfaces as the transport's own error on the record. If neither appears, the message was never decoded -- check transport and decoder eligibility first.

A JSON-RPC response carries no method, so its kind is resolved from the correlated request. If responses show a generic kind, the request they answer was not captured: usually because interception started mid-session.

A shadow endpoint received nothing

  • confirm the substituted value in the delivered message really points at the shadow's URL, not the original upstream: open the message comparison;
  • confirm the shadow is still running (ait intercept shadow list);
  • confirm the receiver actually re-resolves the endpoint. An agent that cached an Agent Card at startup will not follow a substitution made afterwards, and that is a finding about the receiver, not a fault in the shadow.

Shadows bind to loopback only. There is no remote-bind option, so a target on another host cannot reach one.

Lab startup fails

Check for port conflicts first.

ait lab list
ait lab stop LAB_ID

The nine built-in exercises run as separate local processes over loopback or stdio. They need no Docker daemon, model provider, framework package, or external network. If one fails to start, the previous lab's components are usually still holding their ports. Stop it explicitly rather than killing the process, so the cleanup receipt is written.

State adapter or restore fails

  • confirm state_jsonl has a command or supported qdrant/chroma adapter;
  • confirm collection/namespace scope is disposable;
  • run ait state snapshot before the attack arm, not after;
  • distinguish adapter failure from contamination, where restore completed but the digest differed;
  • use ait state restore ... --yes only after reviewing target and scope.

Provider or media delivery fails

  • inspect media before materialization and use PNG, JPEG, WAV, PDF or UTF-8 text;
  • pass deposited manifests in media_manifest_refs;
  • keep ait-media://N indexes within the deposited list;
  • distinguish malformed JSON from SSE framing failures;
  • check request, response and token bounds;
  • remember retries default to zero.

Missing report

ait report looks for lab/report/report.md or reports/report.md.

ait report --run .ait/runs/<run-id>

If no report exists, inspect logs/lab.log and confirm the Assay report render step completed.

Schema or hash verification fails

Use the shared schema path from the repo root:

agentic-redteam/seam/seam transcript verify \
  --schema agentic-redteam/schema/transcript.schema.json \
  --transcript out.json

Failures usually mean the file was truncated, edited by hand, written by an older schema version, or captured with a missing schema path. Transcript verifiers support chain 1.0, 2.0 and 2.1.

Oracle did not observe the side effect

Assay will not accept agent text as proof. Check:

  • the oracle file or callback endpoint was reset before each arm;
  • the target actually writes the tripwire on success;
  • both arms are reaching the same target surface;
  • the expected string or JSON field matches what the target writes.

If the receiver said it did the thing but no oracle observed it, the finding stops at receiver_processed. Agent narration is never evidence.

HTTPS or TLS confusion

Seam is not a transparent TLS interception appliance. Route plaintext test traffic through Seam explicitly, or configure a target/client test mode where Seam receives HTTP, SSE, WebSocket, or stdio application traffic directly.

Remote bind or API access fails

Hardened defaults prefer loopback. Remote listeners, remote intercepts, redirects, and API tokens must be configured explicitly for authorized ranges. Profiles are convenience presets, not hidden permission systems; direct flags remain authoritative.

A2A binding and lifecycle problems

  • Binding rejected: inspect requested/offered/rejected fields in the Agent Card and the transaction. AIT never silently downgrades.
  • Illegal cancel/complete state: compare the expected order with the actual acknowledgements. Timing-only sleeps are not confirmatory.
  • Stream becomes idle: inspect the 30-second default idle bound separately from the five-minute total bound. AIT does not reconnect automatically.
  • Events arrive out of order: duplicate and out-of-order events have separate diagnostics; do not collapse them.
  • Callback authentication fails: verify the credential reference and audience at request time. Do not place a callback secret in target metadata.
  • gRPC bridge exits: verify the a2a-grpc extra, pinned protobuf compatibility, endpoint/authority, TLS references, and message bounds. This bridge supports only official A2A service methods, and AIT does not fall back to HTTP.

Credentials appear in a captured file

They are supposed to. Credential masking was removed so token forging, stripping, downgrade and relay can actually be tested: a substituted destination receiving a bearer token is the credential-relay finding, and masking it would have destroyed the evidence.

What this means for handling: transcripts, session files, shadow observations and rule exports are written 0600. Export with --redacted (the default, a structural allowlist) before handing a record to anyone. --raw is complete capture and is labeled as such. It is never labeled "sanitized".