Skip to content

RFC 002: tool.call events vs LLM tool-use - #3

Merged
brettin merged 2 commits into
rfc/001-run-invocation-and-tool-usefrom
rfc/002-tool-call-events-vs-llm-tool-use
Jun 10, 2026
Merged

RFC 002: tool.call events vs LLM tool-use#3
brettin merged 2 commits into
rfc/001-run-invocation-and-tool-usefrom
rfc/002-tool-call-events-vs-llm-tool-use

Conversation

@brettin

@brettin brettin commented Jun 4, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds RFC 002 distinguishing spec tool-call-event audit telemetry from platform run.outputs.tool_calls and documenting maxToolCalls metering behavior.

Gap IDs

  • GAP-MAX-TOOL-CALLS

Tracking

Part of #1. Base: merge after #2 (RFC 001 PR).

Test plan

  • Review against tool-call-event.schema.json and platform implementation profile

Made with Cursor

Clarifies audit telemetry vs model-requested tool calls and budget metering.

Co-authored-by: Cursor <cursoragent@cursor.com>

@brettin brettin left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

  1. The two-meaning observation is correct. contracts/schemas/events/tool-call-event.schema.json defines tool.call payload 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-137 writes run.outputs.tool_calls = response.tool_calls, where response.tool_calls is the normalized OpenAI function-call list from normalize_openai_tool_calls in services/mag.py:106-122 ({id, name, input}). Same word, two payloads, two lifecycle moments.
  2. The maxToolCalls metering claim matches the code. In aria-server/aria_server/services/mag.py:320, the budget is debited with tool_calls=len(response.tool_calls) if response.tool_calls else 0 inside ModelAccessGateway.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, and tests/test_mag_budget.py exercises exactly that.
  3. Gap is real and unowned. GAP-MAX-TOOL-CALLS is not currently listed in contracts/GAP_DISPOSITION_REGISTER.md, so this RFC plausibly opens that ID rather than re-dispositioning an existing one.

🔍 Suggestions

  1. Name the two concepts distinctly in the proposal. Today both surfaces use the noun "tool call". Consider proposing model.tool_request (or llm.tool_use) for the model-turn artifact in run.outputs, and reserving tool.call strictly for executed-tool audit events. Without a rename, every downstream client will keep conflating them — aria-client/aria_client/cli/tool_agent.py:95-126 already overloads tool_calls for both the assistant message and the run outputs summary.
  2. Spell out the budget semantics in budget-policy.schema.json. The current schema description for maxToolCalls is 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.
  3. Address the emission gap. No path in aria-server actually emits an eventType: tool.call event today — EventType.TOOL_CALL is declared in aria-server/aria_server/api/routes/events.py:30 but run_executor.py only emits journal.run.completed. The RFC should state whether (a) spec tool.call is purely external/optional, (b) the platform owes a tool.call event per executed tool, or (c) the platform should emit it per requested batch. Today the audit stream is silent on tools.
  4. 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 one tool.call event, one per tool, or none.

❓ Open questions

  1. Who emits tool.call audit events when the executor is the client (e.g., aria-client tool_agent.py) rather than the server? Is the client expected to POST them back via /events?
  2. Should tokenCost on a tool.call event 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.
  3. Does maxToolCalls apply per-run or per-budget-scope (task|tenant|user per budget-policy.schema.json)? The metering code aggregates onto Budget.used_tool_calls regardless of run, which suggests scope-wide — worth stating explicitly.
  4. Should aria-langgraph-agent (which today only ticks and never invokes tools) emit tool.call events 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>
@brettin

brettin commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator Author

Amended this RFC with a Status: Implemented section noting that its normative substance has already landed in main via PR #9 ("Tighten RunInvocation companion contract"):

  • Event semantics (model turn vs executed tool) → contracts/companion/run-invocation-interop.md (MAG-turn vs executed-tool telemetry boundary).
  • maxToolCalls budget wording → same file; rewritten from "tool_calls batches per MAG invoke" to "model-returned tool call items per MAG invoke".

The RFC document itself was never on main (the contracts/rfcs/README.md index added by PR #2 currently links to a non-existent file), so merging this PR also fixes that broken link while preserving the design rationale for future readers.

@brettin
brettin merged commit ac11e6b into rfc/001-run-invocation-and-tool-use Jun 10, 2026
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.

2 participants