Repository navigation
feat: add optional run-wide cap on enclave tool calls (--max-num-tool-calls) - #9271
Conversation
--max-num-tool-calls)
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The cap is consistently validated, propagated, enforced, persisted, documented, and covered by focused tests.
Review effort: Balanced
Findings: None
What changed in this PR
Adds an optional run-wide enclave tool-call cap for cost control, enforced and persisted by the enclave MCP broker.
Changes:
- Adds CLI/config/schema support and validation.
- Enforces, persists, advertises, and logs the shared call budget.
- Adds comprehensive tests and documentation.
| File | Description |
|---|---|
src/types/enclave-options.ts |
Defines the cap option. |
src/services/enclave-mcp-service.ts |
Passes the cap to the broker. |
src/services/enclave-dynamic-service.test.ts |
Tests environment propagation. |
src/enclave/tool-call-budget.test.ts |
Tests enforcement and persistence. |
src/config-mapper.ts |
Maps file configuration. |
src/config-file.ts |
Types the configuration key. |
src/config-file-validation.test.ts |
Tests config validation. |
src/config-file-mapping.test.ts |
Tests config mapping. |
src/commands/validators/infrastructure-validator.ts |
Validates the cap and enclave requirement. |
src/commands/validators/infrastructure-validator.test.ts |
Tests startup validation. |
src/commands/build-config.ts |
Builds the runtime option. |
src/cli-options.ts |
Adds the CLI flag. |
src/awf-config-schema.json |
Updates the runtime schema. |
docs/enclaves-architecture.md |
Documents architectural behavior. |
docs/awf-config.schema.json |
Updates the canonical schema. |
docs/awf-config-spec.md |
Specifies cap semantics. |
containers/enclave/mcp-server/tool-call-budget.js |
Implements the persistent budget. |
containers/enclave/mcp-server/server.js |
Initializes the budget. |
containers/enclave/mcp-server/mcp-protocol.js |
Enforces and advertises the cap. |
containers/enclave/mcp-server/config.js |
Loads broker configuration. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
✅ Copilot review passed with no inline comments. @copilot Add the |
Documentation PreviewDocumentation has been built for this PR. To view locally:
Built from commit 0358379 |
✅ Coverage Check PassedOverall Coverage
📁 Per-file Coverage Changes (3 files)
Coverage comparison generated by |
|
✨ The prophecy is fulfilled... Smoke Codex has completed its mystical journey. The stars align. 🌟 Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
To allow these domains, add them to the network:
allowed:
- defaults
- "clients2.google.com"See Network Configuration for more information.
|
|
✅ Security Guard completed successfully! PR #9271 security review complete: no vulnerabilities found. The optional run-wide tool-call cap implementation (tool-call-budget.js and mcp-protocol.js) maintains proper isolation, validates inputs, uses atomic file operations with secure permissions (0o600), and enforces the cap before any handler execution. No security-weakening changes to firewall rules, capabilities, or egress controls detected. Feature is optional and backward compatible.
|
|
✅ Smoke Copilot BYOK completed. Copilot BYOK mode operational. 🔓
|
|
❌ Smoke Copilot BYOK AOAI (api-key) reports failed. AOAI BYOK (api-key) mode investigation needed...
|
|
✅ Build Test Suite completed successfully!
|
|
🔌 Smoke Services — All services reachable! ✅
|
|
❌ Smoke Gemini reports failed. Facets need polishing...
|
|
📡 Smoke OTel Tracing completed. All tracing scenarios validated. ✅
|
|
Smoke Cloud Hypervisor completed. Cloud Hypervisor + Copilot passed.
|
|
📰 VERDICT: Smoke Copilot has concluded. All systems operational. This is a developing story. 🎤
|
|
🛡️ Smoke Copilot Network Isolation confirmed the egress allowlist is enforced. ✅
|
|
❌ Smoke Copilot BYOK AOAI (Entra) reports failed. AOAI BYOK (Entra) mode investigation needed...
|
|
❌ Smoke Claude failed
|
|
Chroot tests passed! Smoke Chroot - All security and functionality tests succeeded.
|
|
EGRESS_RESULT allow=pass deny=pass
Overall: PASS —
|
|
Smoke Copilot: PASS ✅
PR: feat: add optional run-wide cap on enclave tool calls (
|
Smoke Test: Cloud Hypervisor + Copilot
Overall: 2/4 PASS. Network checks (2 & 4) were blocked by the sandbox's non-interactive permission layer before reaching the firewall/network, so egress filtering itself could not be exercised.
|
|
Services smoke test:
Overall: PASS
|
|
OTEL smoke test
|
Smoke Test: Copilot BYOK (Direct) Mode ✅Test Results:
Mode: Direct BYOK ( Status: PASS
|
🏗️ Build Test Suite Results
Overall: 6/8 ecosystems passed — FAIL Failures:
The
|
Smoke Test
Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
To allow these domains, add them to the network:
allowed:
- defaults
- "clients2.google.com"See Network Configuration for more information.
|
Chroot Version Comparison
Result: Not all tests passed (Node.js version mismatch), so the
|
Tool-call volume drives agentic workflow cost. This adds an opt-in cap on how many enclave tool calls an agent can make in one AWF run. It is enforced in
enclave-mcp-server, which already sees every enclave tool request. When the flag is unset, behavior is unchanged.Configuration
--max-num-tool-calls <n>↔ configrateLimiting.maxNumToolCalls. The key lives underrateLimitingbecauseenclavesis an array of entries with no run-wide slot.AWF_ENCLAVE_MAX_TOOL_CALLS, only when set.Enforcement (
containers/enclave/mcp-server/tool-call-budget.js)enclave_run_scriptandenclave_run_agent. It is independent of per-entrymaxInvocationsand of the disclosure ledger.tools/callto a published tool uses one unit. The check runs before the payload-size check, the busy/single-call check, and the handler, so failed and rejected attempts also count. Requests rejected as-32602(no published tool named) are not counted.isErrorresult with the text "Max tool call count reached, no more tool calls are allowed. Make a decision based on what you already have in context."{"status":"error"}.initialize.instructions. AWF can't edit the primary agent's system prompt, so this is the closest equivalent.Max tool call count reached. {toolName, agentName: <executor kind>, sessionID: <runId>, maxToolCalls}. Later denials are not logged, so a retry loop can't flood the logs.{version, runId, used}is written to the broker's private control dir with mode0600and an atomic rename, and the temp file is removed if the write fails. A restarted broker resumes the count for the same run id; any other run id starts at zero. A corrupt state file is treated as zero. If a write fails, the in-memory count keeps enforcing the cap.Decisions on the issue's open questions
awfrun.enclave_run_script? Yes, script calls count.enclave_run_agentcall and is not counted separately.maxModelRequestsandmaxModelTokens.Docs
docs/awf-config-spec.md: CLI↔config mapping line and a new §14.2a.docs/enclaves-architecture.md: summary paragraph.docs/awf-config.schema.json, withsrc/awf-config-schema.jsonregenerated from it.