RFC 002: tool.call events vs LLM tool-use - #3
Conversation
Clarifies audit telemetry vs model-requested tool calls and budget metering. Co-authored-by: Cursor <cursoragent@cursor.com>
brettin
left a comment
There was a problem hiding this comment.
Review: RFC 002 — tool.call events vs LLM tool-use
Overall a useful and accurate distinction: the spec's tool.call event and the platform's run.outputs.tool_calls field share a name but mean different things, and maxToolCalls metering follows the platform meaning rather than the audit one. The RFC is short (12 added lines) and reads more like a stub than a proposal — the diagnosis is right, but the "Proposal" section stops at "clarify" and "align" without saying what the clarified text should be. A few observations and suggestions below.
✅ What works well
- The two-meaning observation is correct.
contracts/schemas/events/tool-call-event.schema.jsondefinestool.callpayload as{runId, toolName, status, latencyMs, tokenCost}— pure post-hoc audit telemetry for one executed tool. By contrast,aria-server/aria_server/services/run_executor.py:130-137writesrun.outputs.tool_calls = response.tool_calls, whereresponse.tool_callsis the normalized OpenAI function-call list fromnormalize_openai_tool_callsinservices/mag.py:106-122({id, name, input}). Same word, two payloads, two lifecycle moments. - The
maxToolCallsmetering claim matches the code. Inaria-server/aria_server/services/mag.py:320, the budget is debited withtool_calls=len(response.tool_calls) if response.tool_calls else 0insideModelAccessGateway.invoke, before any local execution._raise_if_tool_calls_exceeded(mag.py:125-150) then enforces against that count. So "platform counts MAG-returned batches per run, not local agent execution" is precisely what the implementation does, andtests/test_mag_budget.pyexercises exactly that. - Gap is real and unowned.
GAP-MAX-TOOL-CALLSis not currently listed incontracts/GAP_DISPOSITION_REGISTER.md, so this RFC plausibly opens that ID rather than re-dispositioning an existing one.
🔍 Suggestions
- Name the two concepts distinctly in the proposal. Today both surfaces use the noun "tool call". Consider proposing
model.tool_request(orllm.tool_use) for the model-turn artifact inrun.outputs, and reservingtool.callstrictly for executed-tool audit events. Without a rename, every downstream client will keep conflating them —aria-client/aria_client/cli/tool_agent.py:95-126already overloadstool_callsfor both the assistant message and the run outputs summary. - Spell out the budget semantics in
budget-policy.schema.json. The current schema description formaxToolCallsis just{ "type": "integer", "minimum": 0 }. Propose concrete description text: e.g., "count of model-requested tool invocations returned by MAG per run, regardless of whether the client executes them." Without this, operators will assume it caps executed tools and under-provision. - Address the emission gap. No path in
aria-serveractually emits aneventType: tool.callevent today —EventType.TOOL_CALLis declared inaria-server/aria_server/api/routes/events.py:30butrun_executor.pyonly emitsjournal.run.completed. The RFC should state whether (a) spectool.callis purely external/optional, (b) the platform owes atool.callevent per executed tool, or (c) the platform should emit it per requested batch. Today the audit stream is silent on tools. - Cover the streaming case.
MAGStreamChunk.tool_call_delta(mag.py:56) means tool-call shape arrives incrementally; the RFC should say whether deltas roll up into onetool.callevent, one per tool, or none.
❓ Open questions
- Who emits
tool.callaudit events when the executor is the client (e.g.,aria-clienttool_agent.py) rather than the server? Is the client expected to POST them back via/events? - Should
tokenCoston atool.callevent represent tokens consumed by the tool (e.g., a sub-LLM tool) or the tokens the orchestrator spent shaping the call? The schema is ambiguous. - Does
maxToolCallsapply per-run or per-budget-scope (task|tenant|userperbudget-policy.schema.json)? The metering code aggregates ontoBudget.used_tool_callsregardless of run, which suggests scope-wide — worth stating explicitly. - Should
aria-langgraph-agent(which today only ticks and never invokes tools) emittool.callevents when extended, or is that the server's responsibility once it observes the agent's outputs?
The normative substance of RFC 002 (event semantics + maxToolCalls budget alignment) has already landed in contracts/companion/run-invocation-interop.md via PR #9. Retain this RFC as a historical / design-rationale record and note where its intent was realized. Co-Authored-By: Claude Opus 4.6 <noreply@openclaude.dev>
|
Amended this RFC with a Status: Implemented section noting that its normative substance has already landed in
The RFC document itself was never on |
Summary
Adds RFC 002 distinguishing spec
tool-call-eventaudit telemetry from platformrun.outputs.tool_callsand documentingmaxToolCallsmetering behavior.Gap IDs
GAP-MAX-TOOL-CALLSTracking
Part of #1. Base: merge after #2 (RFC 001 PR).
Test plan
tool-call-event.schema.jsonand platform implementation profileMade with Cursor