prime-radiant-inc / tool-fluency
Use when designing, running, or diagnosing Evener tool-fluency experiments for a real built-in, plugin, or newly added tool. Covers probe manifests, model comparisons, semantic oracles, and interpreting fluency failures without ad-hoc transcript parsing.
Tool Fluency
Use this skill when Jesse asks whether a model uses a Evener tool fluently, asks
for tool-fluency scenarios, or adds a new real tool that needs model-facing
coverage.
Required reading
- Read
tools/tool-fluency/README.md. Read
docs/developing-evener/agentic-testing.mdif the Go runner cannot exercise the live
session shape you need.For session/job/watch forensics, use
evener doctoror theagent/doctor
package. Do not hand-parse transcript JSONL.
Core rules
- Test real behavior, not prompt/doc strings.
Use structured probes and semantic oracles. Do not make assertions whose main
claim is "the transcript contains this phrase."Do not write custom Python or jq glue to count tool calls, watches, or
delegate sends. Improve the Go runner orevener doctorwhen a needed
inspection is missing.Separate task success from fluency. A run can complete the task while still
showing tool churn, invalid first arguments, polling, or wrong-tool recovery.- Treat unavailable-by-design tools as
skipped_unavailable, not failures. For future tools, add a probe only after the tool exists in the runtime tool
catalog.
Workflow
- Identify the exact tool or workflow under test.
Confirm which contexts should expose it: root, leaf subagent, coordinator
subagent, bundled agent role, provider behavior tag, or plugin/custom agent.- Define the smallest probe that forces the intended tool decision.
Define a semantic oracle:
- artifact/file state;
- structured tool result;
- session/job/watch/delegate state through
agent/doctor; - public final token only when it is the actual user-visible contract;
- custom Go verifier only when reusable oracles are insufficient.
- Define forbidden calls and fluency metrics separately from pass/fail.
- Run the probe across the requested models and repetitions.
Inspect every failure for root cause before changing prompts, schemas, or
probes.
Runner commands
Catalog currently advertised tools:
go run ./tools/tool-fluency/cmd/evener-fluency catalog --model openai/gpt-5.4-miniRun all current probes:
go run ./tools/tool-fluency/cmd/evener-fluency run \
--build \
--model openai/gpt-5.4-mini \
--fast-cheap-model openai/gpt-5.4-mini \
--clear-openai-api-key \
--probe allRun one probe with an existing binary:
go run ./tools/tool-fluency/cmd/evener-fluency run \
--evener-bin /tmp/evener \
--model openai/gpt-5.4-mini \
--probe read_file.happy_pathRun one probe with an experimental prompt append:
go run ./tools/tool-fluency/cmd/evener-fluency run \
--evener-bin /tmp/evener \
--model openai/gpt-5.4-mini \
--probe read_file.happy_path \
--system-prompt-append tools/tool-fluency/variants/example.mdUse prompt-append variants for experiments, not as a substitute for product
fixes. Keep each variant small and atomic, and run it against the same
probe/model/harness as the failure you are trying to explain.
Run a callback or notification probe with a live session harness:
go run ./tools/tool-fluency/cmd/evener-fluency run \
--harness live \
--model openai/gpt-5.4-mini \
--fast-cheap-model openai/gpt-5.4-mini \
--clear-openai-api-key \
--probe job_watch.observer_callback \
--post-turn-wait 45sUse --harness live when a probe needs SetNotifyFunc or SetKickFunc
wiring, such as observer callbacks, watch deliveries, or notification-driven
parent resumes. Use the default CLI harness for ordinary one-shot tool probes.
Failure classification
Use these categories in reports:
schema: tool definition, strict mode, JSON schema, or provider conversion
made the right call hard or impossible.availability: tool was missing or incorrectly exposed in the context.selection: model chose the wrong tool or avoided the intended tool.arguments: model selected the right tool but supplied invalid or weak args.repair: model failed to recover from a meaningful validation error.interpretation: model got a good tool result but used it incorrectly.churn: extra calls that did not contribute to the task.polling: model repeatedly inspected state instead of waiting for the runtime
signal or callback.plain_message: model emitted assistant text wherecommunicatewas the
required channel.infra: provider quota, hub crash, bad credentials, timeout unrelated to
model behavior.harness: the tool-fluency runner itself failed to launch or drive the
probe (subprocess spawn failure, missing binary, environment/plumbing
issue) before the model had any chance to act. Never attribute this to the
model.
Reporting format
Report both the verdict and the evidence:
probe: job_watch.observer_callback
model: openai/gpt-5.4-mini
status: failed
task_success: true
fluency:
first_call_tool: delegate
validation_errors: 1
forbidden_tool_calls: 0
polling_calls: 0
root_cause: schema
evidence:
session_id: 01...
state_dir: /tmp/...
doctor:
parent job_list count: 0
parent job_status count: 0
observer communicate count: 1
fix: make job_watch optional field X non-strict / clarify repair messageHealthy runs should have no findings. Do not manufacture "looks good" findings.
Forensics
The runner writes result.json, stdout.txt, and stderr.ndjson under each
probe repetition directory. For session/job/watch inspection, prefer:
go run ./cmd/evener doctor transcript "$SID" --state-dir "$STATE" -format outline
go run ./cmd/evener doctor transcript "$SID" --state-dir "$STATE" -count communicate
go run ./cmd/evener doctor tree "$SID" --state-dir "$STATE" --observers
go run ./cmd/evener doctor watches "$SID" --state-dir "$STATE"If a live observer/callback scenario needs a session to remain open across
notification turns, use evener-fluency run --harness live. If that harness
cannot represent the needed shape, use the live scenario process indocs/developing-evener/agentic-testing.md, or improve the Go runner instead of accumulating
shell glue.