Skip to content

feat: a bounded decision, a breaker, fail open on what a compiled answer can't honour - #12

Merged
kbhatnagar1506 merged 1 commit into
mainfrom
feat/runtime-safety
Oct 2, 2026
Merged

kbhatnagar1506 merged 1 commit into
mainfrom
feat/runtime-safety

Conversation

@kbhatnagar1506

Copy link
Copy Markdown
Owner

Makes the wrapper safe to run in production.

Bounded in time

  • The whole decision call takes at most timeout, including name lookup, connect and a slow response.
  • The server is told how long that is (x-agentcompiler-deadline-ms), so it answers in time.
  • In shadow mode the SDK says so (x-agentcompiler-mode: shadow), and the server keeps no conversation state.

Circuit breaker

  • After 5 failures in a row (no answer, a 5xx or a 429), the SDK stops asking for 30 s and calls the model directly.
  • It then lets one call through to see whether AgentCompile is back.

Fails open on what a compiled answer can't honour

  • These requests go to the model without asking AgentCompile: n > 1, a forced tool_choice, a response_format, or legacy functions. The trail records them with the route unsupported.
  • A tool call for a tool that isn't in the request's tools is never answered (fail-open, reason tool not offered).

Behaves like the provider SDKs

  • next(stream) and __anext__ read compiled and captured streams from where they are, as the SDKs' own streams do.

Nothing grows without bound

  • Capture batches stay under 4 MiB; a single call over 7 MiB is dropped and counted.
  • Wrapping a client again reuses the capture sender for the same destination.
  • The trail moves aside at 10 MB.

Tested: 74 tests (16 new in tests/test_hardening.py), ruff clean.

🤖 Generated with Claude Code

…wer can't honour

- The whole decision call takes at most `timeout` (a name lookup or a slow drip included),
  and the server is told how long that is (x-agentcompiler-deadline-ms) and whether it is
  shadow mode (x-agentcompiler-mode: shadow, so it keeps no state).
- After 5 failures in a row the SDK stops asking for 30 s, then lets one call through.
- A request a compiled answer couldn't honour goes to the model without asking: n > 1, a
  forced tool_choice, a response_format, legacy functions. A tool call AgentCompile proposes
  that isn't among the request's tools is never answered.
- next() and __anext__ read compiled and captured streams like the SDKs' own.
- Capture batches stay under 4 MiB (a call over 7 MiB alone is dropped and counted).
- No growth without bound: the trail moves aside at 10 MB, wrapping again reuses the capture
  sender, outcome() keeps one destination and lets finished threads go.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kbhatnagar1506
kbhatnagar1506 merged commit 3f997bf into main Oct 2, 2026
5 checks passed
@kbhatnagar1506
kbhatnagar1506 deleted the feat/runtime-safety branch October 2, 2026 05:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant