# Per-node circuit breakers

An optional circuit breaker can reject model or tool attempts after repeated
transient failures on one node:

```elixir
BeamAgent.API.run("...",
  llm: {MyModelClient, model: "example/model"},
  circuit_breaker: [
    model: [failure_threshold: 3, reset_timeout_ms: 30_000],
    tool: [failure_threshold: 5, reset_timeout_ms: 10_000]
  ]
)
```

`failure_threshold` must be 1–1,000; `reset_timeout_ms` must be 1–3,600,000.
Only returned `:temporarily_unavailable`, `:rate_limited`, and `:timeout`
errors count toward opening a circuit. Successful results and other returned
errors reset the consecutive-failure count. Exceptions retain the existing
runner-crash behavior and do not count as closed-circuit failures.

While open, the operation is not invoked; the run fails with
`run.error == :circuit_open`. After the reset interval, one runner may make a
half-open probe. A successful probe closes the circuit; a transient failure
reopens it. Other callers are rejected while the probe runs. If the probe's
runner dies or cannot obtain rate admission, the circuit reopens without
replaying the operation.

The model key contains the client module and a bounded model identifier; the
tool key contains its module. Numeric policy settings are also part of each
key, so applications should configure one consistent policy per model or
tool. Breaker state is local to one node and is reset if its supervised
process restarts. It is not a cluster-wide provider guarantee. No prompts,
arguments, results, or raw errors enter breaker keys or telemetry.
