find_tool_calls
Search tool call history across agent sessions and subagents, filter by tool name, input/output content, errors, or session, and retrieve subagent cost details.
Instructions
Find every tool call across sessions, cross-agent by default.
redact=True (default) masks secrets in emitted record fields as
[REDACTED_<TYPE>] and adds a redactions type→count dict when
any replacement happened; redact=False returns raw content.
Filters always match the RAW, pre-redaction text.
session scopes the scan to a single session uuid (or a list of
uuids) — same semantics as the query facet. None = every
session; a wide since/until with NO session therefore
surfaces calls from unrelated sessions, so pin it when auditing one
conversation.
Exactly one of tool_name (exact, case-insensitive) or
tool_name_pattern (substring, case-insensitive) must be set.
Optional filters combine with AND: input_contains /
output_contains (case-insensitive substring on the full,
pre-cap input/output), output_excludes (drop records whose
output contains it) and is_error (tri-state: None all,
True failures only, False successes only). output_mode
selects output truncation — "head"/"tail"/"smart";
None is adaptive ("smart" on errors, "head" otherwise).
Each record also carries is_error_reliable (True only for
Claude/OpenCode) plus the wrapper-aware classification: tool_kind
(edit/write/read/bash/task/skill/mcp/
web/other) and tool_resolved — the real name under a
Skill/Task/MCP wrapper (subagent type, skill name, or
"<server>:<tool>"); None when there is no wrapper or the
input carries no name signal.
A record whose call has a correlated result also carries
tool_use_id — the join key back to a spawned subagent's own session
(the child stores it as extra.spawn_tool_use_id). On a spawn
(tool_kind="task") it additionally carries subagent: what the
child COST — model (the model it actually resolved to, which may be a
cheaper pinned tier than the parent's), agent_type (persona),
tokens (EXACT billed usage, source="exact", full token-block
shape), status, duration_ms, tool_uses. Honest gaps: a
background spawn (status="async_launched", sidecar written before the
run exists) reports its model with no tokens key — never a
fabricated zero; its real cost and persona come from
read_session(include_subagents=True) → subagent_rollup.children.
A record carrying several tool results drops the sidecar rather than
billing it to the wrong subagent.
with_subagent_cost=True (opt-in) recovers exactly that for the spawn
records here: each subagent sidecar is JOINED to the spawned child's
own files, adding the persona (agent_type) from the child's
agent-*.meta.json, the models it ran on, its EXACT billed
tokens (source="exact", an estimate is never merged into the
billing field) and child_uuid. So a background spawn — anonymous and
price-less in the launch-time sidecar — becomes a named, priced row. The
child is preferred over the sidecar, which stays the fallback for a child
that cannot be joined (not yet on disk, meta corrupt): its tokens are
then left absent, never zeroed. Default False reads no per-spawn child
file (a cross-corpus scan does not pay the join).
Thin wrapper over :func:ai_r.find_tool_calls.find_tool_calls
that translates the core ValueError contract into the
{"error": "invalid_argument", "message": str(exc)} shape the
MCP client expects.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| agent | No | ||
| limit | No | ||
| since | No | ||
| until | No | ||
| redact | No | ||
| session | No | ||
| is_error | No | ||
| tool_name | No | ||
| output_mode | No | ||
| input_contains | No | ||
| output_contains | No | ||
| output_excludes | No | ||
| tool_name_pattern | No | ||
| with_subagent_cost | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||