From c1ecbccb5cf9bae00837d3de3ad6b7a226bdee9f Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Wed, 4 Mar 2026 01:29:58 -0500 Subject: [PATCH] Add subagent demo and complete tool display name coverage - Add demo/03-subagent.dot, renumber demos 04-08 - Add shell and spawn_agent to tool display name matcher - Add list_dir, web_search, web_fetch, use_skill display args Co-Authored-By: Claude Opus 4.6 --- crates/arc-workflows/src/cli/progress.rs | 7 ++++++- demo/03-subagent.dot | 11 +++++++++++ demo/04-pipeline.dot | 13 ++++++++++++ demo/05-branch-loop.dot | 16 +++++++++++++++ demo/06-parallel.dot | 25 ++++++++++++++++++++++++ demo/07-human-gate.dot | 18 +++++++++++++++++ demo/08-multi-model.dot | 21 ++++++++++++++++++++ 7 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 demo/03-subagent.dot create mode 100644 demo/04-pipeline.dot create mode 100644 demo/05-branch-loop.dot create mode 100644 demo/06-parallel.dot create mode 100644 demo/07-human-gate.dot create mode 100644 demo/08-multi-model.dot diff --git a/crates/arc-workflows/src/cli/progress.rs b/crates/arc-workflows/src/cli/progress.rs index e80ad77ab..a28c8e07f 100644 --- a/crates/arc-workflows/src/cli/progress.rs +++ b/crates/arc-workflows/src/cli/progress.rs @@ -101,12 +101,17 @@ fn tool_display_name(tool_name: &str, arguments: &serde_json::Value) -> String { let path_arg = || arg("path").or_else(|| arg("file_path")).map(|p| truncate(&shorten_path(p), 60)); let detail = match tool_name { - "bash" | "execute_command" => arg("command").map(|c| truncate(c, 60)), + "bash" | "shell" | "execute_command" => arg("command").map(|c| truncate(c, 60)), "glob" => arg("pattern").map(String::from), "grep" | "ripgrep" => arg("pattern").map(|p| truncate(p, 40)), "read_file" | "read" => path_arg(), "write_file" | "write" | "create_file" => path_arg(), "edit_file" | "edit" => path_arg(), + "list_dir" => path_arg(), + "web_search" => arg("query").map(|q| truncate(q, 60)), + "web_fetch" => arg("url").map(|u| truncate(u, 60)), + "spawn_agent" => arg("task").map(|t| truncate(t, 60)), + "use_skill" => arg("skill_name").map(String::from), _ => None, }; diff --git a/demo/03-subagent.dot b/demo/03-subagent.dot new file mode 100644 index 000000000..385fd9102 --- /dev/null +++ b/demo/03-subagent.dot @@ -0,0 +1,11 @@ +digraph SubAgent { + graph [goal="Research and summarize using a sub-agent"] + rankdir=LR + + start [shape=Mdiamond, label="Start"] + exit [shape=Msquare, label="Exit"] + + research [label="Research", prompt="You have a sub-agent available via the spawn_agent tool. Spawn a sub-agent to list the files in the current directory and read the first 10 lines of any README or CLAUDE.md. Then, using the sub-agent's findings, write a 2-sentence summary of the project."] + + start -> research -> exit +} diff --git a/demo/04-pipeline.dot b/demo/04-pipeline.dot new file mode 100644 index 000000000..55c180ca8 --- /dev/null +++ b/demo/04-pipeline.dot @@ -0,0 +1,13 @@ +digraph Pipeline { + graph [goal="Analyze the current directory and suggest improvements"] + rankdir=LR + + start [shape=Mdiamond, label="Start"] + exit [shape=Msquare, label="Exit"] + + scan [label="Scan Files", shape=parallelogram, script="find . -maxdepth 2 -type f | head -30"] + analyze [label="Analyze", prompt="Review the file listing from the previous step. Identify what kind of project this is and summarize its structure in 3-4 bullet points.", codergen_mode="one_shot", reasoning_effort="low"] + suggest [label="Suggest", prompt="Based on the analysis, suggest 3 concrete improvements to the project structure. Be specific and actionable.", codergen_mode="one_shot", reasoning_effort="low"] + + start -> scan -> analyze -> suggest -> exit +} diff --git a/demo/05-branch-loop.dot b/demo/05-branch-loop.dot new file mode 100644 index 000000000..df066bd16 --- /dev/null +++ b/demo/05-branch-loop.dot @@ -0,0 +1,16 @@ +digraph BranchLoop { + graph [goal="Create a Python script that passes its test suite"] + rankdir=LR + + start [shape=Mdiamond, label="Start"] + exit [shape=Msquare, label="Exit"] + + plan [label="Plan", prompt="Plan a small Python script (fizzbuzz.py) and a test file (test_fizzbuzz.py) using pytest. Describe what you will create.", codergen_mode="one_shot", reasoning_effort="low"] + implement [label="Implement", prompt="Create fizzbuzz.py and test_fizzbuzz.py as planned. Write the files to disk."] + validate [label="Validate", shape=parallelogram, script="python -m pytest test_fizzbuzz.py -v 2>&1 || true"] + gate [shape=diamond, label="Tests passing?"] + + start -> plan -> implement -> validate -> gate + gate -> exit [label="Pass", condition="outcome=success"] + gate -> implement [label="Fix"] +} diff --git a/demo/06-parallel.dot b/demo/06-parallel.dot new file mode 100644 index 000000000..1c9335268 --- /dev/null +++ b/demo/06-parallel.dot @@ -0,0 +1,25 @@ +digraph Parallel { + graph [goal="Perform a multi-perspective code review"] + rankdir=LR + + start [shape=Mdiamond, label="Start"] + exit [shape=Msquare, label="Exit"] + + fork [label="Fork Analysis", shape=component, join_policy="wait_all", error_policy="continue"] + + security [label="Security Audit", prompt="Examine the codebase for security concerns: hardcoded secrets, injection risks, unsafe dependencies. List findings as bullet points.", codergen_mode="one_shot", reasoning_effort="low"] + architecture [label="Architecture Review", prompt="Assess the codebase architecture: separation of concerns, dependency structure, modularity. List findings as bullet points.", codergen_mode="one_shot", reasoning_effort="low"] + quality [label="Code Quality", prompt="Check code quality: naming conventions, dead code, test coverage gaps, error handling. List findings as bullet points.", codergen_mode="one_shot", reasoning_effort="low"] + + merge [label="Merge Findings", shape=tripleoctagon] + report [label="Final Report", prompt="Synthesize the security, architecture, and code quality findings into a prioritized summary report with top 5 action items.", codergen_mode="one_shot"] + + start -> fork + fork -> security + fork -> architecture + fork -> quality + security -> merge + architecture -> merge + quality -> merge + merge -> report -> exit +} diff --git a/demo/07-human-gate.dot b/demo/07-human-gate.dot new file mode 100644 index 000000000..f537a3fb9 --- /dev/null +++ b/demo/07-human-gate.dot @@ -0,0 +1,18 @@ +digraph HumanGate { + graph [goal="Propose and implement a README improvement"] + rankdir=LR + + start [shape=Mdiamond, label="Start"] + exit [shape=Msquare, label="Exit"] + + draft [label="Draft Proposal", prompt="Read the README.md (or note its absence). Propose a specific improvement: either create one or enhance the existing one. Describe your proposed changes clearly but do NOT make any changes yet.", codergen_mode="one_shot"] + approve [label="Approve Changes?", shape=hexagon] + apply [label="Apply Changes", prompt="Apply the proposed README changes that were approved."] + skip [label="Skip", prompt="Acknowledged. No changes made.", codergen_mode="one_shot", reasoning_effort="low"] + + start -> draft -> approve + approve -> apply [label="[A] Approve"] + approve -> skip [label="[S] Skip"] + apply -> exit + skip -> exit +} diff --git a/demo/08-multi-model.dot b/demo/08-multi-model.dot new file mode 100644 index 000000000..302c92b02 --- /dev/null +++ b/demo/08-multi-model.dot @@ -0,0 +1,21 @@ +digraph MultiModel { + graph [ + goal="Build and review a utility function using multiple models", + model_stylesheet=" + * { llm_model: claude-haiku-4-5; llm_provider: anthropic; reasoning_effort: low; } + .coding { llm_model: claude-sonnet-4-5; llm_provider: anthropic; reasoning_effort: high; } + #review { llm_model: claude-sonnet-4-5; llm_provider: anthropic; reasoning_effort: high; } + " + ] + rankdir=LR + + start [shape=Mdiamond, label="Start"] + exit [shape=Msquare, label="Exit"] + + spec [label="Write Spec", prompt="Write a brief spec for a TypeScript string utility module with 3 functions: slugify, truncate, and capitalize. Output the spec only.", codergen_mode="one_shot"] + implement [label="Implement", prompt="Implement the TypeScript string utility module from the spec. Write it to string-utils.ts.", class="coding"] + test [label="Write Tests", prompt="Write tests for the string utility module using Bun's test runner. Write to string-utils.test.ts.", class="coding"] + review [label="Code Review", prompt="Review the implementation and tests. Check for edge cases, type safety, and correctness. Provide a brief verdict.", codergen_mode="one_shot"] + + start -> spec -> implement -> test -> review -> exit +}