#5749·nanobot

Expose stable tool invocation context for idempotent side effects

Author: xiexiahaoCreated Sep 12, 2026Updated Sep 12, 2026
Labelsenhancement

Problem / Motivation

AgentRunner already has a stable provider tool-call ID when dispatching a tool, and runtime checkpoints use tool-call IDs to distinguish pending and completed work. However, the tool implementation does not receive the identity of the logical tool invocation. RequestContext exposes session_key and turn_id, but there is no per-tool invocation context carrying tool_call_id. This matters for tools with external side effects such as sending messages or email, creating remote records, invoking API mutations, or submitting work to another service. If execution is retried or resumed, a tool supporting downstream idempotency has no canonical nanobot invocation identity it can reuse as an idempotency key.

Proposed Solution

Expose the current logical tool invocation identity through a small runtime-context primitive:

@dataclass(frozen=True)
class ToolInvocationContext:
    tool_call_id: str
    invocation_key: str | None = None

AgentRunner would bind this context only while executing the corresponding tool call, and reset it afterward. A helper such as current_tool_invocation_context() would let context-aware tools or extensions inspect the identity without changing tool schemas or exposing internal metadata to the model. A deterministic invocation_key could be derived from session_key + tool_call_id, with an appropriate fallback without a session key. The same logical tool call should have the same key; nanobot need not persist results or enforce exactly-once execution.

Alternatives Considered

Mutating request-level metadata would be unsafe when multiple tool calls execute concurrently. A nested ContextVar scoped to one invocation preserves the existing request context and follows asyncio task isolation. This proposal does not add automatic retries, a durable idempotency database, exactly-once guarantees, a scheduler or task ledger, checkpoint changes, automatic replay, tool-schema changes, or new user-facing configuration. Downstream systems remain responsible for enforcing idempotency.

Related Component

Other

Additional Context

Suggested tests: single-call identity; parallel calls see their own IDs and keys; context cleanup; stable keys for the same (session_key, tool_call_id); distinct keys for different calls; and a defined SDK or ephemeral no-session fallback. Nanobot already has RequestContext identities, ToolCallRequest.id, and ContextVar-based runtime context.