Sovara Tool CLI¶
so-tool is a CLI interface designed for programmatic interaction with the Sovara dataflow graph system. It's primarily intended for use by coding agents like Claude Code, but can also be used for scripting and automation.
Design Principles¶
- Machine-readable output: All commands output JSON to stdout for easy parsing
- Blocking by default: Commands block until completion and return results
- Idempotent where possible: Same inputs produce same outputs
Commands¶
so-tool record¶
Records a script execution and blocks until completion.
Options:
| Option | Description |
|---|---|
-m, --module |
Run as Python module (like python -m) |
--run-name <name> |
Human-readable name for this run |
--timeout <seconds> |
Timeout in seconds (terminates script if exceeded) |
Output:
On timeout:
so-tool probe¶
Queries session state, graph topology, or specific nodes.
so-tool probe <session_id>
so-tool probe <session_id> --node <node_id>
so-tool probe <session_id> --nodes <id1,id2,...>
Options:
| Option | Description |
|---|---|
--node <id> |
Return detailed info for single node |
--nodes <ids> |
Return detailed info for multiple nodes (comma-separated) |
--preview |
Truncate strings to 20 characters |
--input |
Only show input content |
--output |
Only show output content |
--key-regex <pattern> |
Filter keys using regex on flattened paths |
Key Regex:
The --key-regex option filters the input/output dictionaries by matching against flattened key paths. Lists use index notation:
messages.0.contentmatches the first message's contentmessages.*contentmatches content in any messagechoices.0.messagematches the first choice's message
Output (default - session overview):
{
"session_id": "uuid",
"name": "Run 42",
"status": "finished",
"timestamp": "2024-01-15T10:30:00",
"node_count": 5,
"nodes": [
{
"node_id": "node-1",
"label": "GPT-4",
"parent_ids": [],
"child_ids": ["node-2"]
}
],
"edges": [
{"source": "node-1", "target": "node-2"}
]
}
Output (single node):
{
"node_id": "node-1",
"session_id": "uuid",
"api_type": "httpx.Client.send",
"label": "GPT-4",
"timestamp": "2024-01-15T10:30:05",
"parent_ids": [],
"child_ids": ["node-2"],
"has_input_overwrite": false,
"stack_trace": ["file.py:42 in main()", "file.py:15 in call_llm()"],
"input": {...},
"output": {...}
}
so-tool experiments¶
Lists experiments from the database.
so-tool experiments
so-tool experiments --range :50
so-tool experiments --range 50:100
so-tool experiments --regex "eval.*"
Options:
| Option | Description |
|---|---|
--range <start:end> |
Range of experiments (default: :50) |
--regex <pattern> |
Filter by name using regex |
Range format:
:50- First 50 experiments50:100- Experiments 50-9910:- All from index 10 onwards
so-tool edit-and-rerun¶
Edits a single key in a node and immediately reruns the session. Always creates a new run.
so-tool edit-and-rerun <session_id> <node_id> --input <key> <value>
so-tool edit-and-rerun <session_id> <node_id> --output <key> <value>
Options:
| Option | Description |
|---|---|
--input <key> <value> |
Edit an input key (mutually exclusive with --output) |
--output <key> <value> |
Edit an output key (mutually exclusive with --input) |
--run-name <name> |
Name for the new run (default: "Edit of |
--timeout <seconds> |
Timeout for the rerun |
Key format:
Keys use flattened dot-notation matching the output from probe. Examples:
- choices.0.message.content - First choice's message content
- messages.0.content - First message's content
Value:
The value can be a literal string or a path to a file. If the path exists, the file contents are used.
Output:
{
"status": "completed",
"session_id": "new-uuid",
"node_id": "node-1",
"edited_field": "output",
"edited_key": "choices.0.message.content",
"exit_code": 0,
"duration_seconds": 12.5
}
so-tool install-skill¶
Interactive setup for Claude Code integration.
Behavior:
- Prompts for target project directory (with tab-completion)
- Copies
SKILL.mdto.claude/skills/sovara/ - Optionally adds Bash permissions to
.claude/settings.local.json
Node Metadata Schema¶
Every node (API call) contains the following metadata:
| Field | Type | Description |
|---|---|---|
node_id |
string | Unique identifier (UUID) |
session_id |
string | Parent session identifier |
label |
string | Model name or tool name |
api_type |
string | API type (e.g., "httpx.Client.send") |
timestamp |
string | When the call was made |
stack_trace |
string[] | Call stack at invocation (filtered to user code) |
parent_ids |
string[] | IDs of nodes whose output fed into this input |
child_ids |
string[] | IDs of nodes that consume this output |
input |
object | The API call input (flattened to_show structure) |
output |
object | The API call response (flattened to_show structure) |
has_input_overwrite |
bool | Whether input has been edited |
Implementation Details¶
Process Spawning¶
so-tool record uses subprocess.Popen with:
- Session file for IPC (agent_runner writes session_id after handshake)
- Blocking wait for completion
Database Access¶
Most commands query the SQLite database directly via DatabaseManager. The database stores:
- Experiments (session metadata, graph topology)
- LLM calls (inputs, outputs, overwrites)
- Attachments (cached file references)
Edit Validation¶
When editing input/output:
- Parse the flattened key and resolve it in the
to_showstructure - Merge with existing
rawstructure usingmerge_filtered_into_raw() - For outputs, validate conversion to API object type
- Store as overwrite (preserves original)
Stack Trace Filtering¶
Stack traces are captured at LLM call time and filtered to show only user code:
- Removes Sovara infrastructure frames (agent_runner, database_manager)
- Removes frames from
sovara/directory (unless developing Sovara itself) - Returns as list of strings for readability