toolpath-convo
Provider-agnostic conversation types and traits for AI coding tools.
This crate defines a common vocabulary for representing conversations from any AI coding assistant (Claude, Codex, OpenCode, etc.) without coupling consumer code to provider-specific data formats.
Write your conversation analysis once, swap providers without changing a line.
Overview
Types define the common data model:
| Type | What it represents |
|---|---|
Turn |
A single conversational turn (text, thinking, tool uses, model, tokens, environment, delegations) |
Role |
Who produced the turn: User, Assistant, System, Other(String) |
ConversationView |
A complete conversation: ordered turns, timestamps, aggregate usage, files changed |
ConversationMeta |
Lightweight metadata (no turns loaded) |
ToolInvocation |
A tool call within a turn, with optional ToolCategory classification |
ToolResult |
The result of a tool call |
ToolCategory |
Toolpath's classification ontology: FileRead, FileWrite, FileSearch, Shell, Network, Delegation |
TokenUsage |
Input/output/cache token counts |
EnvironmentSnapshot |
Working directory and VCS branch/revision at time of a turn |
DelegatedWork |
A sub-agent delegation: prompt, nested turns, result |
WatcherEvent |
A Turn (new), TurnUpdated (enriched with tool results), or Progress event — with as_turn(), as_progress(), is_update(), turn_id() helpers for ergonomic dispatch |
Traits define how providers expose their data:
| Trait | What it does |
|---|---|
ConversationProvider |
List and load conversations from any source |
ConversationWatcher |
Poll for new conversational events |
Usage
use ;
// Provider crates implement ConversationProvider.
// Consumer code works against the trait:
Tool classification
ToolCategory is toolpath's own ontology for what a tool invocation does,
independent of provider-specific naming. Provider crates map their tool
names into these categories; None means the tool isn't recognized.
| Category | Meaning |
|---|---|
FileRead |
Read a file — no side effects |
FileWrite |
Write, edit, create, or delete a file |
FileSearch |
Search or discover files by name or content pattern |
Shell |
Shell or terminal command execution |
Network |
Web fetch, search, API call |
Delegation |
Spawn a sub-agent or delegate work |
Consumers can filter by category without knowing provider tool vocabularies:
let writes: = turn.tool_uses.iter
.filter
.collect;
Watching
Dispatch on WatcherEvent with match — three variants, exhaustive:
use ;
for event in watcher.poll?
Convenience methods (as_turn(), as_progress(), is_update(), turn_id())
are available for cases where the distinction between Turn and TurnUpdated
collapses — e.g. a formatting pipeline that takes a turn + flag:
// When Turn/TurnUpdated go through the same path:
if let Some = event.as_turn
// Keying/dedup without matching two variants:
if let Some = event.turn_id
Provider-specific metadata lives in Turn.extra, namespaced by provider (e.g. turn.extra["claude"]). This keeps the common schema clean while giving consumers opt-in access to provider internals.
Provider implementations
| Provider | Crate |
|---|---|
| Claude Code | toolpath-claude |
Part of Toolpath
This crate is part of the Toolpath workspace. See also:
toolpath-- core provenance types and query APItoolpath-claude-- Claude conversation providertoolpath-git-- derive from git historytoolpath-dot-- Graphviz DOT renderingtoolpath-cli-- unified CLI (cargo install toolpath-cli)- RFC -- full format specification