Fault Injection: the failure taxonomy at run time

Pick a fault. Watch the same execute_tool wrapper classify it, retry it or not, and feed back the outcome.

Wrapper config: deadline 2.0s  ·  up to 2 retries  ·  backoff x2 (0.5s, then 1.0s)  ·  retries fire ONLY on transient failures.
Call
Five categories, one recovery policy each
transient RETRY (bounded, exponential backoff), then feed back if exhausted
permanent FEED BACK as an Observation, no retry
empty-result FEED BACK as an Observation, no retry
malformed FEED BACK (Part 1 validator catch), no retry
unknown-tool FEED BACK (Part 1 validator catch), no retry

"Feed back" means the failure becomes an Observation the controller reads and reasons about, not a crash. The loop survives a bad tool call the way it survives a good one.

The side-effecting tool: why a retry needs a guard

A refund posts, then its acknowledgement times out. The wrapper retries. Without a guard, that retry refunds the customer twice.

Same transient, both sides: process_refund(ORD-5510, $80.00)  ·  attempt 1 posts to the gateway, then the confirmation times out  →  the wrapper schedules retry 1/2 after 0.5s.
no idempotency guard UNSAFE
attempt 1 → posts $80.00, ack times out (TransientError)
transient → retry 1/2 after 0.5s backoff
attempt 2 → posts $80.00 AGAIN, ack returns OK
ledger: 2 refunds posted for ORD-5510 → $160.00 DOUBLE REFUND. The blind retry re-ran the side effect.
with idempotency guard (by order_id) EXACTLY ONCE
attempt 1 → records ORD-5510, posts $80.00, ack times out
transient → retry 1/2 after 0.5s backoff
attempt 2 → guard sees ORD-5510, skips re-acting, returns prior result
ledger: 1 refund recorded for ORD-5510 → $80.00 Exactly once. The retry hit the guard and skipped re-acting.
Note: a read-only tool is safe to retry for free; a tool that moves money is not. The guard records the effect keyed by order_id before the point where the call can fail, so a retry recognizes it. This is a local in-memory guard; Part 9 hardens it into durable idempotency keys that survive a process crash.