Add stateless Task tool for subagent delegation#61
Conversation
Implements the core infrastructure for stateless task delegation, enabling agents to discover callable targets and render task messages without maintaining runtime state. Changes: - llm-coding-tools-core: Added TASK context with delegation guidance text - llm-coding-tools-agents: Created task.rs with callable-target discovery and caching - llm-coding-tools-serdesai: Added task module with definition and message helpers - Added TaskTargetSummary struct with name, description, tools, and has_task - Used caching to avoid O(n²) complexity in has_task computation - Added 14 inline tests covering edge cases for all three crates Benefits: - Enables stateless task delegation without runtime state management - Provides consistent callable-target discovery with O(n) complexity - Follows existing context pattern for TASK constant - All new code includes comprehensive test coverage
Task is now a first-class catalog entry flowing through the normal permission filter. The build path attaches a stub executor that returns a "not yet implemented" error until the real executor lands. Changes: - Added `Task` variant to `ToolCatalogKind` and `DEFAULT_TOOLS` - Added `callable_target_summaries` to `PreparedBuild`, computed in `prepare_build` - Added `ToolCatalogKind::Task` arm in `finish_builder` — skips when no callable targets - Added `StubTaskExecutor` placeholder returning execution_failed error - Removed redundant `default_tools_exclude_task_and_keep_names_unique` test - Fixed `task.txt` to include "stateless, one-shot delegation" in first line Benefits: - Task flows through the same permission pipeline as all other tools - Agents automatically get the Task tool when allowed and callable targets exist
The delegated agent already runs in a fresh session with its own system prompt, so wrapping the prompt with "This is a delegated task..." headers was redundant and wasted tokens. Callers should use input.prompt directly. Changes: - Deleted task/message.rs and build_delegated_message function - Removed re-export from task/mod.rs - Fixed context test that asserted "stateless" on task.txt (never present) Benefits: - Aligns delegation behavior with opencode reference implementation - Eliminates unnecessary prompt wrapping and token overhead
…uild Replaces the stub Task executor with a working implementation that validates delegation targets and builds sub-agents on demand. The build path now requires callers to provide their own credential source instead of silently reading from the process environment. Changes: - Added TaskTool and TaskHandle for real one-shot task delegation - Added AgentRuntimeTaskExt and task-enabled build API - Changed AgentRuntimeExt::build to require caller-provided credentials - Generalized credential parameters to accept any CredentialLookup - Extracted prepare_build and attach_standard_tools as shared internals - Made PreparedBuild pub(super) with accessor methods for reuse - Replaced StubTaskExecutor with target validation and agent construction - Updated example to use explicit credential overrides instead of env vars Benefits: - Agents can now actually delegate work to sub-agents via the Task tool - Callers retain full control over credential sourcing - Build internals are reusable for both plain and task-enabled paths
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #61 +/- ##
==========================================
+ Coverage 80.54% 80.58% +0.04%
==========================================
Files 87 93 +6
Lines 2950 3152 +202
==========================================
+ Hits 2376 2540 +164
- Misses 574 612 +38
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
Ports commit 8792813a onto the current branch with API adaptations for the newer credential-injected build_with_task() signature. Changes: - Added examples/serdesai-task.rs runnable example - Added examples/agents/orchestrator.md primary agent - Added examples/agents/reader.md subagent with read-only tools - Added Task Tool section to README with usage example - Added serdesai-agents and serdesai-task to README Examples list - Reworded Agent Runtime intro to reference OpenCode-style agents Benefits: - End-to-end example of the Task delegation pattern - Clearer naming (orchestrator/reader vs task/file-reader)
a7f4c05 to
efd5b57
Compare
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughThis pull request implements a comprehensive Task delegation system for multi-agent coordination. It introduces the Task tool across the core, agents, and SerdesAI crates, adds TaskSettings for managing delegation depth constraints, and implements permission-based callable target discovery. New modules in runtime handle task-specific logic including validation, depth checking, and credential-aware agent construction. SerdesAI's build flow is extended to accept credentials and conditionally include Task tool support based on available callable targets. Examples demonstrate stateless task delegation patterns. Possibly related PRs
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment Tip Migrating from UI to YAML configuration.Use the |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (1)
src/llm-coding-tools-core/src/context/task.txt (1)
17-18: Consider removing redundant "back" from "return back".Static analysis flagged the redundancy in "return a single message back" and "return back to you". While minor, cleaner phrasing improves readability.
Suggested rewording
-2. When the agent is done, it will return a single message back to you. The result returned by the agent is not visible to the user. To show the user the result, you should send a text message back to the user with a concise summary of the result. The output includes a task_id you can reuse later to continue the same subagent session. -3. Each agent invocation starts with a fresh context unless you provide task_id to resume the same subagent session (which continues with its previous messages and tool outputs). When starting fresh, your prompt should contain a highly detailed task description for the agent to perform autonomously and you should specify exactly what information the agent should return back to you in its final and only message to you. +2. When the agent is done, it will return a single message to you. The result returned by the agent is not visible to the user. To show the user the result, you should send a text message to the user with a concise summary of the result. The output includes a task_id you can reuse later to continue the same subagent session. +3. Each agent invocation starts with a fresh context unless you provide task_id to resume the same subagent session (which continues with its previous messages and tool outputs). When starting fresh, your prompt should contain a highly detailed task description for the agent to perform autonomously and you should specify exactly what information the agent should return to you in its final and only message to you.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/llm-coding-tools-core/src/context/task.txt` around lines 17 - 18, Edit the sentences in src/llm-coding-tools-core/src/context/task.txt to remove the redundant "back" in phrases like "return a single message back to you" and "return back to you"; update them to "return a single message to you" and "return to you" respectively, ensuring the surrounding meaning stays identical and the references to task_id and agent behavior remain unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/llm-coding-tools-agents/src/runtime/task.rs`:
- Around line 84-93: The loop that builds `targets` currently includes the
caller itself and can enable recursive self-calls; update the selection logic in
the block that iterates `for target in agents` (the code using
`matches!(target.mode, AgentMode::All | AgentMode::Subagent)`,
`has_explicit_task_permission`, `task_rules.is_allowed`, and
`targets.push(*target)`) to exclude the caller (compare `target.name` against
the current agent id) or add a delegation-depth/visited-agent guard that threads
into `TaskHandle::execute` to reject or stop delegation when a max depth or
already-visited agent is detected; ensure the chosen approach prevents adding
the caller to `targets` and propagates the depth/visited state into the
`TaskHandle::execute` delegation path.
In `@src/llm-coding-tools-core/src/context/task.txt`:
- Around line 25-28: The XML snippet has mismatched tag names: the opening tag
is <example_agent_descriptions> but the closing tag is
</example_agent_description>; update the closing tag to match the opener (use
</example_agent_descriptions>) so the element names are consistent (check the
block containing "code-reviewer" and "greeting-responder" and ensure both
opening and closing tags for example_agent_descriptions match).
In `@src/llm-coding-tools-serdesai/examples/serdesai-task.rs`:
- Around line 18-19: Replace the hardcoded secret in the API_KEY_VALUE constant:
remove the real-looking key and either set API_KEY_VALUE to an empty placeholder
or change the code to read the key from the environment (e.g., use
std::env::var("SYNTHETIC_API_KEY") where API_KEY_NAME and API_KEY_VALUE are
referenced). Also add a clear runtime check where the key is consumed (so
callers using API_KEY_VALUE handle missing/empty values with an explicit error
or panic) to avoid silently using an empty value.
In `@src/llm-coding-tools-serdesai/src/agent_runtime/build.rs`:
- Around line 129-131: prepare_build computes callable Task targets via
summarize_callable_targets(runtime.catalog(), name) but then filters tools with
Ruleset::from_permission_config(&agent.permission) using a default-deny when
permission.task is absent, so Task tools never get attached; change the
materialization so Task inclusion follows the same default rule as callable
target computation: when agent.permission.task is None treat allowed Task
targets as "all non-primary targets" (or conversely require explicit permission
in both places), and apply that same allowed-task policy when calling
ruleset.filter_allowed_tools(runtime.tools()) — update the logic around
Ruleset::from_permission_config, permission.task handling, and the call sites
filter_allowed_tools and summarize_callable_targets to use a single source of
truth for allowed Task targets (e.g., normalize allowed task list before
filtering tools).
In `@src/llm-coding-tools-serdesai/src/task/handle.rs`:
- Around line 92-130: The validate_target method currently implements an
implicit-allow semantics when the caller has no explicit task permission (it
only checks Ruleset::from_permission_config(&caller.permission).is_allowed(...)
if caller.permission contains tool_names::TASK), which diverges from Ruleset's
default-deny documentation; either add a concise inline comment above
validate_target (or above the has_explicit_task_permission logic) describing
this intentional opt-in design (mentioning validate_target, caller.permission,
Ruleset, tool_names::TASK, and that AgentMode::Primary targets are always
denied) or add a unit test covering the "no explicit task permission" case that
verifies delegation is allowed to non-Primary targets to prevent regressions.
---
Nitpick comments:
In `@src/llm-coding-tools-core/src/context/task.txt`:
- Around line 17-18: Edit the sentences in
src/llm-coding-tools-core/src/context/task.txt to remove the redundant "back" in
phrases like "return a single message back to you" and "return back to you";
update them to "return a single message to you" and "return to you"
respectively, ensuring the surrounding meaning stays identical and the
references to task_id and agent behavior remain unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 410d0293-81db-4009-9a58-5492b55f187e
📒 Files selected for processing (19)
src/llm-coding-tools-agents/src/lib.rssrc/llm-coding-tools-agents/src/runtime/mod.rssrc/llm-coding-tools-agents/src/runtime/task.rssrc/llm-coding-tools-agents/src/runtime/tool_catalog.rssrc/llm-coding-tools-core/src/context/mod.rssrc/llm-coding-tools-core/src/context/task.txtsrc/llm-coding-tools-serdesai/README.mdsrc/llm-coding-tools-serdesai/examples/agents/orchestrator.mdsrc/llm-coding-tools-serdesai/examples/agents/reader.mdsrc/llm-coding-tools-serdesai/examples/serdesai-agents.rssrc/llm-coding-tools-serdesai/examples/serdesai-task.rssrc/llm-coding-tools-serdesai/src/agent_runtime/build.rssrc/llm-coding-tools-serdesai/src/agent_runtime/mod.rssrc/llm-coding-tools-serdesai/src/agent_runtime/task.rssrc/llm-coding-tools-serdesai/src/lib.rssrc/llm-coding-tools-serdesai/src/task/definition.rssrc/llm-coding-tools-serdesai/src/task/handle.rssrc/llm-coding-tools-serdesai/src/task/mod.rssrc/llm-coding-tools-serdesai/src/task/tool.rs
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Build and Test (Async/Tokio) (windows-latest, x86_64-pc-windows-msvc, false)
- GitHub Check: Build and Test (Blocking) (windows-latest, x86_64-pc-windows-msvc, false)
- GitHub Check: Build and Test (Blocking) (macos-latest, aarch64-apple-darwin, false)
- GitHub Check: Build and Test (Async/Tokio) (macos-latest, aarch64-apple-darwin, false)
- GitHub Check: Build and Test (Async/Tokio) (ubuntu-latest, x86_64-unknown-linux-gnu, false)
🧰 Additional context used
📓 Path-based instructions (1)
src/**/*.rs
📄 CodeRabbit inference engine (src/AGENTS.md)
src/**/*.rs: Preallocate collections when size is known or estimable usingString::with_capacity(estimated_len),Vec::with_capacity(count), orBufReader::with_capacity(size, reader)
Prefer&str/&[T]returns over owned types when lifetime allows
UseCow<'_, str>for conditional ownership (e.g.,String::from_utf8_lossy)
Use&'static strfor compile-time constant strings
Reuse buffers by calling.clear()and reusingVec/Stringinstead of reallocating
Use const generics for compile-time branching (e.g.,<const LINE_NUMBERS: bool>)
Use#[inline]on small, hot-path functions
Prefercoreoverstdwhere possible (e.g.,core::memoverstd::mem)
Usememchrcrate for fast byte searching over manual iteration
Keep modules under 500 lines (excluding tests); split if larger
Placeusestatements inside functions only for#[cfg]conditional compilation
Document public items with///and add examples in docs where helpful
Use//!for module-level documentation
Use [TypeName] rustdoc links instead of backticks in documentation
Files:
src/llm-coding-tools-core/src/context/mod.rssrc/llm-coding-tools-serdesai/src/task/mod.rssrc/llm-coding-tools-agents/src/runtime/mod.rssrc/llm-coding-tools-serdesai/src/agent_runtime/mod.rssrc/llm-coding-tools-agents/src/runtime/task.rssrc/llm-coding-tools-serdesai/src/task/handle.rssrc/llm-coding-tools-serdesai/src/lib.rssrc/llm-coding-tools-serdesai/src/task/definition.rssrc/llm-coding-tools-agents/src/runtime/tool_catalog.rssrc/llm-coding-tools-serdesai/examples/serdesai-task.rssrc/llm-coding-tools-serdesai/examples/serdesai-agents.rssrc/llm-coding-tools-agents/src/lib.rssrc/llm-coding-tools-serdesai/src/agent_runtime/task.rssrc/llm-coding-tools-serdesai/src/task/tool.rssrc/llm-coding-tools-serdesai/src/agent_runtime/build.rs
🧠 Learnings (3)
📚 Learning: 2026-02-07T22:53:26.067Z
Learnt from: CR
Repo: Sewer56/llm-coding-tools PR: 0
File: src/AGENTS.md:0-0
Timestamp: 2026-02-07T22:53:26.067Z
Learning: Organize code with `llm-coding-tools-serdesai/` containing `src/absolute/`, `src/allowed/`, `src/schema.rs`, and `src/convert.rs` for serdesAI framework implementations
Applied to files:
src/llm-coding-tools-serdesai/src/task/mod.rssrc/llm-coding-tools-serdesai/src/agent_runtime/mod.rssrc/llm-coding-tools-serdesai/src/lib.rssrc/llm-coding-tools-serdesai/src/task/definition.rssrc/llm-coding-tools-serdesai/examples/serdesai-task.rssrc/llm-coding-tools-serdesai/examples/serdesai-agents.rssrc/llm-coding-tools-serdesai/src/agent_runtime/task.rssrc/llm-coding-tools-serdesai/README.mdsrc/llm-coding-tools-serdesai/src/task/tool.rs
📚 Learning: 2026-02-07T22:53:26.067Z
Learnt from: CR
Repo: Sewer56/llm-coding-tools PR: 0
File: src/AGENTS.md:0-0
Timestamp: 2026-02-07T22:53:26.067Z
Learning: Organize code with `llm-coding-tools-core/` as framework-agnostic core library containing `src/tools/`, `src/path/`, `src/error.rs`, `src/output.rs`, and `src/util.rs`
Applied to files:
src/llm-coding-tools-serdesai/src/task/mod.rssrc/llm-coding-tools-serdesai/src/lib.rssrc/llm-coding-tools-serdesai/examples/serdesai-agents.rssrc/llm-coding-tools-agents/src/lib.rssrc/llm-coding-tools-serdesai/README.md
📚 Learning: 2026-02-07T22:53:26.067Z
Learnt from: CR
Repo: Sewer56/llm-coding-tools PR: 0
File: src/AGENTS.md:0-0
Timestamp: 2026-02-07T22:53:26.067Z
Learning: Applies to src/**/*.rs : Document public items with `///` and add examples in docs where helpful
Applied to files:
src/llm-coding-tools-serdesai/examples/serdesai-task.rs
🪛 LanguageTool
src/llm-coding-tools-core/src/context/task.txt
[style] ~16-~16: Consider a more expressive alternative.
Context: ...r possible, to maximize performance; to do that, use a single message with multipl...
(DO_ACHIEVE)
[style] ~17-~17: Using “back” with the verb “return” may be redundant.
Context: ...s done, it will return a single message back to you. The result returned by the agen...
(RETURN_BACK)
[style] ~18-~18: Consider using just “return”.
Context: ...actly what information the agent should return back to you in its final and only message to...
(RETURN_BACK)
🔇 Additional comments (26)
src/llm-coding-tools-serdesai/src/agent_runtime/mod.rs (1)
1-25: LGTM!The module organization is clean with appropriate public/crate-private visibility scoping. Documentation properly uses rustdoc [
TypeName] link syntax as per coding guidelines, and the new task-related exports are well-documented in the module header.src/llm-coding-tools-core/src/context/mod.rs (2)
47-48: LGTM!The new
TASKconstant follows the established pattern for context constants and includes appropriate documentation.
260-265: LGTM!Good test coverage verifying the task context contains expected delegation-related keywords.
src/llm-coding-tools-serdesai/examples/agents/orchestrator.md (1)
1-15: LGTM!Well-structured example agent demonstrating permission-based task delegation. The permission syntax using
task:with pattern rules ("*": deny,"reader": allow) aligns with thePermissionRule::Patterntype from the config schema. The agent instructions clearly describe stateless delegation semantics.src/llm-coding-tools-serdesai/examples/agents/reader.md (1)
1-15: LGTM!Clean subagent definition with appropriate permissions. The
task: denyrule correctly prevents recursive delegation, and the read-only tool permissions (read,glob,grep) match the agent's stated purpose. This pairs well with the orchestrator example.src/llm-coding-tools-agents/src/runtime/mod.rs (1)
18-22: LGTM!The new task module is cleanly integrated with proper public exports and documentation. The API surface (
callable_targets,summarize_callable_targets,TaskTargetSummary) is appropriately scoped and documented in the module header.Also applies to: 44-44, 50-50
src/llm-coding-tools-agents/src/runtime/tool_catalog.rs (1)
54-55: LGTM!The
Taskvariant is cleanly added toToolCatalogKindwith proper documentation. TheDEFAULT_TOOLSarray size and entries are correctly updated, and test coverage is maintained.Also applies to: 58-58, 68-68
src/llm-coding-tools-serdesai/examples/serdesai-agents.rs (1)
27-30: LGTM!Good refactoring to use
CredentialResolverinstead of direct environment variable manipulation. Thewithout_env()constructor with conditional override is cleaner and safer for example code.Also applies to: 51-51
src/llm-coding-tools-serdesai/examples/serdesai-task.rs (1)
21-66: LGTM!The example cleanly demonstrates the task-enabled build flow with proper async handling and Arc-wrapped shared resources.
src/llm-coding-tools-serdesai/src/task/mod.rs (1)
1-17: LGTM!Module organization is clean with appropriate visibility boundaries. Public API is limited to
render_task_targetsandtask_tool_definition, while implementation details remain crate-private.src/llm-coding-tools-serdesai/src/lib.rs (2)
11-11: LGTM!New task module correctly added to the public API surface.
50-53: LGTM!Re-exports cleanly expose the new task-enabled build APIs alongside existing credential-based builds.
src/llm-coding-tools-serdesai/src/task/definition.rs (3)
11-30: LGTM!Proper capacity preallocation with
String::with_capacity. The sorted rendering provides stable output for LLM consumption. As per coding guidelines:String::with_capacity(estimated_len)is correctly used.
32-56: LGTM!Schema fields correctly match
TaskInputstruct:description,prompt, andsubagent_typeare required;session_idandcommandare optional. The.expect()is acceptable since the schema is statically defined.
58-126: LGTM!Tests cover key scenarios: sorting, content rendering, empty input handling, and tool definition validation.
src/llm-coding-tools-agents/src/lib.rs (1)
14-18: LGTM!New task-related exports (
callable_targets,summarize_callable_targets,TaskTargetSummary) appropriately extend the public API for task delegation support.src/llm-coding-tools-serdesai/README.md (2)
114-148: LGTM!Clear documentation of the Task tool with a complete usage example. The note about
session_idrejection and pointer to the lower-level helper is helpful.
158-163: LGTM!Example commands clearly describe the two new delegation modes (no delegation vs. single-hop Task).
src/llm-coding-tools-serdesai/src/task/handle.rs (3)
64-90: LGTM!The
executemethod correctly:
- Rejects unsupported
session_idearly- Validates target before building
- Maps build/run errors to
ToolErrorwith contextThe input clone on line 78 is necessary since
inputis moved into the error closure.
133-228: LGTM!Test fixtures are well-structured with helper functions for creating agents, permissions, and test contexts. The
pattern_taskhelper correctly constructs pattern-based permission rules.
230-368: LGTM!Comprehensive test coverage for validation scenarios: unknown targets, primary mode rejection, permission denial, and session_id rejection. Each test properly asserts on error type and message content.
src/llm-coding-tools-serdesai/src/task/tool.rs (4)
20-44: LGTM!Clean struct design with
Box<str>for the caller name (avoiding String overhead for a fixed value). The constructor acceptsimpl Into<Box<str>>for ergonomic usage.
46-79: LGTM!
Tooltrait implementation correctly:
- Delegates definition to
task_tool_definition- Parses input with proper error mapping
- Uses the stored
caller_namefor execute context- The
.expect()on serialization is safe sinceTaskOutputcontains onlyString
81-90: LGTM!
ToolContextimplementation provides consistent naming viatool_names::TASKand returns the appropriate context string.
92-123: LGTM!Tests verify the tool definition matches targets and that NAME/context constants are correctly wired.
src/llm-coding-tools-serdesai/src/agent_runtime/task.rs (1)
107-116: Nice reuse of the existing build pipeline.Reusing
prepare_buildandattach_standard_toolshere keeps task-enabled builds aligned with the plain builder and avoids a second tool/prompt assembly path.
There was a problem hiding this comment.
🧹 Nitpick comments (2)
src/llm-coding-tools-serdesai/README.md (2)
148-148: Clarify the session_id rejection constraint.The statement "session_id is rejected" is mentioned without context. Readers may not understand what session_id refers to or why it's rejected in Task calls.
📋 Suggested clarification
-Each Task call builds and runs the subagent once; `session_id` is rejected. Use [`build_agent_with_credentials_and_task`] for the lower-level helper. See [examples/serdesai-task.rs](examples/serdesai-task.rs). +Each Task call builds and runs the subagent once (stateless execution). The Task tool does not support stateful sessions, so `session_id` parameters are rejected. Use [`build_agent_with_credentials_and_task`] for the lower-level helper. See [examples/serdesai-task.rs](examples/serdesai-task.rs).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/llm-coding-tools-serdesai/README.md` at line 148, Clarify that the Task call API (the Task type/function) does not accept or persist a session identifier: update the README line to state that Task builds and runs a subagent once and any provided session_id will be rejected or ignored (i.e., Task is single-run and does not create a reusable session), and point readers to build_agent_with_credentials_and_task for use cases that need a persistent session or to pass session_id (see examples/serdesai-task.rs for usage); reference Task, session_id, and build_agent_with_credentials_and_task in the text so readers know which symbols are affected.
127-127: Use a more obvious placeholder path.The hardcoded path
/path/to/your/project/examplesmight confuse readers as it appears to be a real system path. Consider using a more conventional placeholder pattern.📝 Suggested improvement
-let examples_root = PathBuf::from("/path/to/your/project/examples"); +let examples_root = PathBuf::from("./examples"); // Path to your agent definitionsor
-let examples_root = PathBuf::from("/path/to/your/project/examples"); +let examples_root = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("examples");🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/llm-coding-tools-serdesai/README.md` at line 127, The placeholder path assigned to examples_root (let examples_root = PathBuf::from("/path/to/your/project/examples");) is ambiguous—replace it with a clearer, conventional placeholder such as a path using angle-bracket or env-var style (e.g. "<PROJECT_ROOT>/examples" or "${PROJECT_ROOT}/examples") and update the PathBuf::from argument accordingly so readers understand it is not a real filesystem path; keep the variable name examples_root and the use of PathBuf::from unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src/llm-coding-tools-serdesai/README.md`:
- Line 148: Clarify that the Task call API (the Task type/function) does not
accept or persist a session identifier: update the README line to state that
Task builds and runs a subagent once and any provided session_id will be
rejected or ignored (i.e., Task is single-run and does not create a reusable
session), and point readers to build_agent_with_credentials_and_task for use
cases that need a persistent session or to pass session_id (see
examples/serdesai-task.rs for usage); reference Task, session_id, and
build_agent_with_credentials_and_task in the text so readers know which symbols
are affected.
- Line 127: The placeholder path assigned to examples_root (let examples_root =
PathBuf::from("/path/to/your/project/examples");) is ambiguous—replace it with a
clearer, conventional placeholder such as a path using angle-bracket or env-var
style (e.g. "<PROJECT_ROOT>/examples" or "${PROJECT_ROOT}/examples") and update
the PathBuf::from argument accordingly so readers understand it is not a real
filesystem path; keep the variable name examples_root and the use of
PathBuf::from unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 2671c797-c658-490d-98cd-ef52607e8c27
📒 Files selected for processing (4)
src/llm-coding-tools-serdesai/README.mdsrc/llm-coding-tools-serdesai/examples/agents/orchestrator.mdsrc/llm-coding-tools-serdesai/examples/agents/reader.mdsrc/llm-coding-tools-serdesai/examples/serdesai-task.rs
🚧 Files skipped from review as they are similar to previous changes (1)
- src/llm-coding-tools-serdesai/examples/serdesai-task.rs
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Build and Test (Async/Tokio) (windows-latest, x86_64-pc-windows-msvc, false)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2026-02-07T22:53:26.067Z
Learnt from: CR
Repo: Sewer56/llm-coding-tools PR: 0
File: src/AGENTS.md:0-0
Timestamp: 2026-02-07T22:53:26.067Z
Learning: Organize code with `llm-coding-tools-serdesai/` containing `src/absolute/`, `src/allowed/`, `src/schema.rs`, and `src/convert.rs` for serdesAI framework implementations
Applied to files:
src/llm-coding-tools-serdesai/README.md
📚 Learning: 2026-02-07T22:53:26.067Z
Learnt from: CR
Repo: Sewer56/llm-coding-tools PR: 0
File: src/AGENTS.md:0-0
Timestamp: 2026-02-07T22:53:26.067Z
Learning: Organize code with `llm-coding-tools-core/` as framework-agnostic core library containing `src/tools/`, `src/path/`, `src/error.rs`, `src/output.rs`, and `src/util.rs`
Applied to files:
src/llm-coding-tools-serdesai/README.md
🔇 Additional comments (4)
src/llm-coding-tools-serdesai/examples/agents/reader.md (1)
1-15: Reader agent contract is clear and correctly constrained.The permission block and prompt instructions are aligned: this agent is read-only and explicitly non-delegating, which matches the intended subagent role.
src/llm-coding-tools-serdesai/examples/agents/orchestrator.md (1)
1-15: Orchestrator policy is well-scoped and permission-safe.The front matter and behavioral instructions are internally consistent: only
readeris callable, and the single-call stateless delegation rule is clearly specified.src/llm-coding-tools-serdesai/README.md (2)
95-112: LGTM!The Agent Runtime section accurately documents the updated API with credential support. The example correctly shows the three-parameter signature and proper import of
CredentialResolver.
159-163: LGTM!The updated examples section clearly describes the new agent runtime and task delegation examples, with helpful distinctions between stateful and stateless approaches.
The closing tag for `<example_agent_descriptions>` was missing the trailing "s", producing `</example_agent_description>`. Changes: - Corrected closing tag to `</example_agent_descriptions>`
…cursion Task delegation now tracks a per-call depth (root starts at 0) and enforces a shared runtime-wide max depth, defaulting to 3 hops. Self- delegation and diamond-shaped call graphs remain allowed; only unbounded recursion is prevented. Changes: - Added TaskSettings (core) with const DEFAULT_MAX_DEPTH of 3 - Added task_settings field and .max_task_depth() / .task_settings() to AgentRuntimeBuilder - Task tool is omitted at build time when depth limit is reached - TaskHandle::execute rejects calls as defense-in-depth if Task tool is present at limit - Re-exported TaskSettings from agents and serdesai crates Benefits: - Prevents A -> A -> A -> ... without blocking legitimate self-delegation or A -> B -> A - Framework-agnostic setting in core; any integration can use TaskSettings - Both build-time and runtime guards ensure the limit is always enforced
There was a problem hiding this comment.
Actionable comments posted: 4
♻️ Duplicate comments (1)
src/llm-coding-tools-serdesai/src/agent_runtime/build.rs (1)
129-144: 🛠️ Refactor suggestion | 🟠 MajorNormalize Task gating before deriving tools and targets.
prepare_buildstill decides Task availability in two places:Ruleset::from_permission_config(...).filter_allowed_tools(...)for the tool itself, andsummarize_callable_targets(...)for the callable subagents. Keeping those paths separate makes the feature easy to desynchronize, and downstream at Lines 209-219attach_standard_toolswill quietly skip Task if only one side says “yes”. Please drive both decisions from the same normalized Task-allowance result.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/llm-coding-tools-serdesai/src/agent_runtime/build.rs` around lines 129 - 144, prepare_build currently computes Task availability in two places (Ruleset::from_permission_config(...).filter_allowed_tools(...) and summarize_callable_targets(...)), risking desynchronization; refactor prepare_build to first compute a single normalized Task-allowance result (e.g., let task_allowance = Ruleset::from_permission_config(&agent.permission) or a normalized structure derived from it) and pass that same result into both filter_allowed_tools(runtime.tools()) and summarize_callable_targets(runtime.catalog(), name) (or modify those functions to accept the normalized allowance), so both tools and callable_target_summaries are derived from the identical gating decision used later by attach_standard_tools.
🧹 Nitpick comments (3)
src/llm-coding-tools-core/src/context/task.txt (1)
15-22: Document delegation depth limits in Usage Notes.Given runtime depth limiting, this section should mention that Task delegation can be rejected after max depth is reached, so callers know how to handle/avoid it.
Proposed addition
6. If the agent description mentions that it should be used proactively, then you should try your best to use it without the user having to ask for it first. Use your judgement. +7. Task delegation depth may be capped by runtime settings. If a Task call is rejected due to depth limits, complete the work directly or return a clear fallback summary.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/llm-coding-tools-core/src/context/task.txt` around lines 15 - 22, Update the "Usage Notes" section in task.txt to document the runtime task delegation depth limit: explicitly state that delegation/starting subagents can be rejected once the configured max delegation depth is reached, explain callers may receive a rejection or error and should handle retrying with reduced delegation or continuing the task locally, and reference the task_id/resume behavior in point 3 so callers know to prefer resuming existing subagent sessions rather than creating deeper nested delegations.src/llm-coding-tools-serdesai/src/agent_runtime/task.rs (1)
164-192: Extract the shared task fixtures.
catalog()andcredentials()are effectively duplicated here and insrc/llm-coding-tools-serdesai/src/task/handle.rs:208-236. A small#[cfg(test)]helper would keep the provider/model setup from drifting between the two suites.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/llm-coding-tools-serdesai/src/agent_runtime/task.rs` around lines 164 - 192, The catalog() and credentials() functions are duplicated across test files; extract them into a single #[cfg(test)] test-helper module and reuse it from both places. Create a test-only module (e.g., mod test_fixtures) that defines pub(crate) fn catalog() -> ModelCatalog and pub(crate) fn credentials() -> Arc<CredentialResolver<false>> (preserving the ProviderSource, ModelInfo, ProviderModelSource and resolver setup), then replace the local definitions in both task.rs and the other file with calls to these shared helpers; ensure visibility/imports so tests can call test_fixtures::catalog() and test_fixtures::credentials().src/llm-coding-tools-core/src/tools/task.rs (1)
121-132: Add a chain-based regression for the documented depth contract.The new docs promise self-delegation and diamond-shaped call graphs remain valid until
max_depth, but this test only locks in the raw<boundary. AnA -> B -> Astyle case in the runtime path would better protect that guarantee.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/llm-coding-tools-core/src/tools/task.rs` around lines 121 - 132, Add a chain-based regression test to ensure the delegation depth contract treats revisits in a call chain (e.g., A -> B -> A) correctly: create a test (e.g., task_settings_chain_delegation_allows_self_delegation_until_max_depth) that uses TaskSettings::with_max_depth(3) and asserts allows_delegation returns true for chain depths representing A (0), A->B (1) and A->B->A (2) but false at depth 3; reference TaskSettings::with_max_depth and TaskSettings::allows_delegation to locate where to add the test and lock in the documented behavior for self-delegation/diamond graphs.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/llm-coding-tools-agents/src/runtime/mod.rs`:
- Around line 12-23: The module docs are stale: update the `default_tools()`
bullet in the top-level doc comment to include the new Task tool (e.g. mention
ToolCatalogKind::Task or "task" in the standard tool set list), so the docs
match the added ToolCatalogKind::Task entry in the runtime catalog; modify the
`default_tools()` description text near the `ToolCatalogEntry`/`ToolCatalogKind`
bullets to include "task" (or "Task") alongside read, write, edit, glob, grep,
bash, webfetch, todo.
In `@src/llm-coding-tools-core/src/context/task.txt`:
- Around line 3-6: The documentation contradicts itself: the Task constructor
requires a subagent_type but the example omits it; update the example and
wording so the required parameter is present—modify the example Task invocation
(the example using Task(description="Check the file", prompt="/check-file
path/to/file.py")) to include subagent_type (e.g.,
Task(subagent_type="your_agent", description="Check the file",
prompt="/check-file path/to/file.py")) and add a brief note in the Task usage
section that subagent_type is mandatory when constructing Task instances.
- Line 56: Replace the malformed example assistant response string that reads
"I'm going to use the Task tool to launch the with the greeting-responder agent"
with a grammatically correct sentence such as "I'm going to use the Task tool to
launch the greeting-responder agent" (or "I'm going to use the Task tool to
launch the greeting-responder agent with the Task tool" if you prefer explicit
phrasing); update the assistant example string in task.txt (the assistant:
"...") so it no longer contains the duplicated "the" and correctly references
the greeting-responder agent.
In `@src/llm-coding-tools-serdesai/README.md`:
- Around line 112-149: The README example imports ModelsDevCatalog but doesn't
mention the extra crate dependency; update the docs to tell users to add the
llm-coding-tools-models-dev crate to their Cargo.toml (or workspace) before
using ModelsDevCatalog::load(), and mention that the example uses
load_result.catalog from ModelsDevCatalog; reference the symbol ModelsDevCatalog
and the example usage (load_result.catalog) so readers know which dependency to
add.
---
Duplicate comments:
In `@src/llm-coding-tools-serdesai/src/agent_runtime/build.rs`:
- Around line 129-144: prepare_build currently computes Task availability in two
places (Ruleset::from_permission_config(...).filter_allowed_tools(...) and
summarize_callable_targets(...)), risking desynchronization; refactor
prepare_build to first compute a single normalized Task-allowance result (e.g.,
let task_allowance = Ruleset::from_permission_config(&agent.permission) or a
normalized structure derived from it) and pass that same result into both
filter_allowed_tools(runtime.tools()) and
summarize_callable_targets(runtime.catalog(), name) (or modify those functions
to accept the normalized allowance), so both tools and callable_target_summaries
are derived from the identical gating decision used later by
attach_standard_tools.
---
Nitpick comments:
In `@src/llm-coding-tools-core/src/context/task.txt`:
- Around line 15-22: Update the "Usage Notes" section in task.txt to document
the runtime task delegation depth limit: explicitly state that
delegation/starting subagents can be rejected once the configured max delegation
depth is reached, explain callers may receive a rejection or error and should
handle retrying with reduced delegation or continuing the task locally, and
reference the task_id/resume behavior in point 3 so callers know to prefer
resuming existing subagent sessions rather than creating deeper nested
delegations.
In `@src/llm-coding-tools-core/src/tools/task.rs`:
- Around line 121-132: Add a chain-based regression test to ensure the
delegation depth contract treats revisits in a call chain (e.g., A -> B -> A)
correctly: create a test (e.g.,
task_settings_chain_delegation_allows_self_delegation_until_max_depth) that uses
TaskSettings::with_max_depth(3) and asserts allows_delegation returns true for
chain depths representing A (0), A->B (1) and A->B->A (2) but false at depth 3;
reference TaskSettings::with_max_depth and TaskSettings::allows_delegation to
locate where to add the test and lock in the documented behavior for
self-delegation/diamond graphs.
In `@src/llm-coding-tools-serdesai/src/agent_runtime/task.rs`:
- Around line 164-192: The catalog() and credentials() functions are duplicated
across test files; extract them into a single #[cfg(test)] test-helper module
and reuse it from both places. Create a test-only module (e.g., mod
test_fixtures) that defines pub(crate) fn catalog() -> ModelCatalog and
pub(crate) fn credentials() -> Arc<CredentialResolver<false>> (preserving the
ProviderSource, ModelInfo, ProviderModelSource and resolver setup), then replace
the local definitions in both task.rs and the other file with calls to these
shared helpers; ensure visibility/imports so tests can call
test_fixtures::catalog() and test_fixtures::credentials().
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: a6ffd335-d544-40b9-8af7-8f51de109d85
📒 Files selected for processing (15)
src/llm-coding-tools-agents/README.mdsrc/llm-coding-tools-agents/src/lib.rssrc/llm-coding-tools-agents/src/runtime/builder.rssrc/llm-coding-tools-agents/src/runtime/mod.rssrc/llm-coding-tools-agents/src/runtime/state.rssrc/llm-coding-tools-core/README.mdsrc/llm-coding-tools-core/src/context/task.txtsrc/llm-coding-tools-core/src/lib.rssrc/llm-coding-tools-core/src/tools/mod.rssrc/llm-coding-tools-core/src/tools/task.rssrc/llm-coding-tools-serdesai/README.mdsrc/llm-coding-tools-serdesai/src/agent_runtime/build.rssrc/llm-coding-tools-serdesai/src/agent_runtime/task.rssrc/llm-coding-tools-serdesai/src/lib.rssrc/llm-coding-tools-serdesai/src/task/handle.rs
✅ Files skipped from review due to trivial changes (1)
- src/llm-coding-tools-agents/README.md
🚧 Files skipped from review as they are similar to previous changes (1)
- src/llm-coding-tools-agents/src/lib.rs
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Build and Test (Blocking) (macos-latest, aarch64-apple-darwin, false)
- GitHub Check: Build and Test (Async/Tokio) (ubuntu-latest, x86_64-unknown-linux-gnu, false)
- GitHub Check: Build and Test (Async/Tokio) (windows-latest, x86_64-pc-windows-msvc, false)
- GitHub Check: Build and Test (Async/Tokio) (macos-latest, aarch64-apple-darwin, false)
🧰 Additional context used
📓 Path-based instructions (1)
src/**/*.rs
📄 CodeRabbit inference engine (src/AGENTS.md)
src/**/*.rs: Preallocate collections when size is known or estimable usingString::with_capacity(estimated_len),Vec::with_capacity(count), orBufReader::with_capacity(size, reader)
Prefer&str/&[T]returns over owned types when lifetime allows
UseCow<'_, str>for conditional ownership (e.g.,String::from_utf8_lossy)
Use&'static strfor compile-time constant strings
Reuse buffers by calling.clear()and reusingVec/Stringinstead of reallocating
Use const generics for compile-time branching (e.g.,<const LINE_NUMBERS: bool>)
Use#[inline]on small, hot-path functions
Prefercoreoverstdwhere possible (e.g.,core::memoverstd::mem)
Usememchrcrate for fast byte searching over manual iteration
Keep modules under 500 lines (excluding tests); split if larger
Placeusestatements inside functions only for#[cfg]conditional compilation
Document public items with///and add examples in docs where helpful
Use//!for module-level documentation
Use [TypeName] rustdoc links instead of backticks in documentation
Files:
src/llm-coding-tools-core/src/tools/mod.rssrc/llm-coding-tools-core/src/lib.rssrc/llm-coding-tools-agents/src/runtime/state.rssrc/llm-coding-tools-agents/src/runtime/builder.rssrc/llm-coding-tools-core/src/tools/task.rssrc/llm-coding-tools-serdesai/src/lib.rssrc/llm-coding-tools-agents/src/runtime/mod.rssrc/llm-coding-tools-serdesai/src/agent_runtime/task.rssrc/llm-coding-tools-serdesai/src/task/handle.rssrc/llm-coding-tools-serdesai/src/agent_runtime/build.rs
🧠 Learnings (3)
📚 Learning: 2026-02-07T22:53:26.067Z
Learnt from: CR
Repo: Sewer56/llm-coding-tools PR: 0
File: src/AGENTS.md:0-0
Timestamp: 2026-02-07T22:53:26.067Z
Learning: Organize code with `llm-coding-tools-core/` as framework-agnostic core library containing `src/tools/`, `src/path/`, `src/error.rs`, `src/output.rs`, and `src/util.rs`
Applied to files:
src/llm-coding-tools-core/src/tools/mod.rssrc/llm-coding-tools-core/src/lib.rssrc/llm-coding-tools-serdesai/src/lib.rssrc/llm-coding-tools-serdesai/README.mdsrc/llm-coding-tools-agents/src/runtime/mod.rs
📚 Learning: 2026-02-07T22:53:26.067Z
Learnt from: CR
Repo: Sewer56/llm-coding-tools PR: 0
File: src/AGENTS.md:0-0
Timestamp: 2026-02-07T22:53:26.067Z
Learning: Organize code with `llm-coding-tools-serdesai/` containing `src/absolute/`, `src/allowed/`, `src/schema.rs`, and `src/convert.rs` for serdesAI framework implementations
Applied to files:
src/llm-coding-tools-serdesai/src/lib.rssrc/llm-coding-tools-serdesai/README.mdsrc/llm-coding-tools-serdesai/src/agent_runtime/task.rssrc/llm-coding-tools-serdesai/src/task/handle.rs
📚 Learning: 2026-02-07T22:53:26.067Z
Learnt from: CR
Repo: Sewer56/llm-coding-tools PR: 0
File: src/AGENTS.md:0-0
Timestamp: 2026-02-07T22:53:26.067Z
Learning: Applies to src/**/*.rs : Document public items with `///` and add examples in docs where helpful
Applied to files:
src/llm-coding-tools-serdesai/src/lib.rs
🪛 GitHub Check: Build and Test (Blocking) (ubuntu-latest, x86_64-unknown-linux-gnu, false)
src/llm-coding-tools-serdesai/src/agent_runtime/task.rs
[warning] 132-132:
Diff in /home/runner/work/llm-coding-tools/llm-coding-tools/src/llm-coding-tools-serdesai/src/agent_runtime/task.rs
[warning] 126-126:
Diff in /home/runner/work/llm-coding-tools/llm-coding-tools/src/llm-coding-tools-serdesai/src/agent_runtime/task.rs
[warning] 4-4:
Diff in /home/runner/work/llm-coding-tools/llm-coding-tools/src/llm-coding-tools-serdesai/src/agent_runtime/task.rs
🪛 LanguageTool
src/llm-coding-tools-core/src/context/task.txt
[style] ~16-~16: Consider a more expressive alternative.
Context: ...r possible, to maximize performance; to do that, use a single message with multipl...
(DO_ACHIEVE)
[style] ~17-~17: Using “back” with the verb “return” may be redundant.
Context: ...s done, it will return a single message back to you. The result returned by the agen...
(RETURN_BACK)
[style] ~18-~18: Consider using just “return”.
Context: ...actly what information the agent should return back to you in its final and only message to...
(RETURN_BACK)
🔇 Additional comments (1)
src/llm-coding-tools-serdesai/src/task/handle.rs (1)
83-96: Good defense-in-depth on max depth.
execute()rechecks the runtime limit even though the build path already strips the Task tool at that depth, so leaked tool registrations still fail closed.
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/llm-coding-tools-serdesai/src/agent_runtime/task.rs (1)
219-220: Variable shadows imported module name.The variable
tool_namesshadows the importedtool_namesmodule. While Rust resolvestool_names::TASKcorrectly to the module, this naming collision reduces readability. Consider renaming the variable tonamesorattached_tools.This pattern repeats at lines 253, 279, 316, and 349.
♻️ Suggested fix
- let tool_names: Vec<_> = agent.tools().iter().map(|t| t.name()).collect(); - assert!(!tool_names.contains(&tool_names::TASK)); + let names: Vec<_> = agent.tools().iter().map(|t| t.name()).collect(); + assert!(!names.contains(&tool_names::TASK));🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/llm-coding-tools-serdesai/src/agent_runtime/task.rs` around lines 219 - 220, The local variable named tool_names shadows the imported module tool_names, which harms readability; rename the variable returned from agent.tools().iter().map(|t| t.name()).collect() (and the other occurrences at the same pattern) to a non-conflicting identifier such as names or attached_tools and update subsequent uses and assertions (e.g., change assert!(!tool_names.contains(&tool_names::TASK)) to assert!(!names.contains(&tool_names::TASK))) so the module reference tool_names::TASK remains unambiguous; ensure you update all repeated instances at the same code pattern in this file.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src/llm-coding-tools-serdesai/src/agent_runtime/task.rs`:
- Around line 219-220: The local variable named tool_names shadows the imported
module tool_names, which harms readability; rename the variable returned from
agent.tools().iter().map(|t| t.name()).collect() (and the other occurrences at
the same pattern) to a non-conflicting identifier such as names or
attached_tools and update subsequent uses and assertions (e.g., change
assert!(!tool_names.contains(&tool_names::TASK)) to
assert!(!names.contains(&tool_names::TASK))) so the module reference
tool_names::TASK remains unambiguous; ensure you update all repeated instances
at the same code pattern in this file.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 7c29c45e-88ab-4b97-b048-49ddc1f25963
📒 Files selected for processing (1)
src/llm-coding-tools-serdesai/src/agent_runtime/task.rs
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Build and Test (Async/Tokio) (macos-latest, aarch64-apple-darwin, false)
- GitHub Check: Build and Test (Blocking) (windows-latest, x86_64-pc-windows-msvc, false)
- GitHub Check: Build and Test (Blocking) (macos-latest, aarch64-apple-darwin, false)
- GitHub Check: Build and Test (Async/Tokio) (ubuntu-latest, x86_64-unknown-linux-gnu, false)
- GitHub Check: Build and Test (Async/Tokio) (windows-latest, x86_64-pc-windows-msvc, false)
🧰 Additional context used
📓 Path-based instructions (1)
src/**/*.rs
📄 CodeRabbit inference engine (src/AGENTS.md)
src/**/*.rs: Preallocate collections when size is known or estimable usingString::with_capacity(estimated_len),Vec::with_capacity(count), orBufReader::with_capacity(size, reader)
Prefer&str/&[T]returns over owned types when lifetime allows
UseCow<'_, str>for conditional ownership (e.g.,String::from_utf8_lossy)
Use&'static strfor compile-time constant strings
Reuse buffers by calling.clear()and reusingVec/Stringinstead of reallocating
Use const generics for compile-time branching (e.g.,<const LINE_NUMBERS: bool>)
Use#[inline]on small, hot-path functions
Prefercoreoverstdwhere possible (e.g.,core::memoverstd::mem)
Usememchrcrate for fast byte searching over manual iteration
Keep modules under 500 lines (excluding tests); split if larger
Placeusestatements inside functions only for#[cfg]conditional compilation
Document public items with///and add examples in docs where helpful
Use//!for module-level documentation
Use [TypeName] rustdoc links instead of backticks in documentation
Files:
src/llm-coding-tools-serdesai/src/agent_runtime/task.rs
🧠 Learnings (1)
📚 Learning: 2026-02-07T22:53:26.067Z
Learnt from: CR
Repo: Sewer56/llm-coding-tools PR: 0
File: src/AGENTS.md:0-0
Timestamp: 2026-02-07T22:53:26.067Z
Learning: Organize code with `llm-coding-tools-serdesai/` containing `src/absolute/`, `src/allowed/`, `src/schema.rs`, and `src/convert.rs` for serdesAI framework implementations
Applied to files:
src/llm-coding-tools-serdesai/src/agent_runtime/task.rs
🔇 Additional comments (2)
src/llm-coding-tools-serdesai/src/agent_runtime/task.rs (2)
1-6: Use rustdoc links in module documentation.Per coding guidelines, use
[TypeName]rustdoc links instead of backticks for type references.📝 Suggested fix
//! Task-enabled SerdesAI runtime builders. //! //! # Public API -//! - [`AgentRuntimeTaskExt`] - Builds a runnable agent with conditional Task support. -//! - [`build_agent_with_credentials_and_task`] - Same build path with explicit shared credentials. +//! - [`AgentRuntimeTaskExt`] - Builds a runnable agent with conditional Task support. +//! - [`build_agent_with_credentials_and_task`] - Same build path with explicit shared credentials.Wait, looking again, the doc already uses
[...]syntax. That's the correct rustdoc link format. Let me re-check.
1-119: LGTM on the core implementation.The task-enabled runtime extension is well-structured:
- Clean trait design with
AgentRuntimeTaskExt- Appropriate use of
Arcfor shared context across delegations- Correct
#[inline]on small accessor- Good separation between public API and internal
build_task_enabled_agent
…f user prompts Sub-agents invoked by the task tool previously received the task prompt as a plain user message. Now they receive a synthetic tool-call / tool-return conversation pair, so the sub-agent sees the invocation as a tool result rather than a user prompt. Changes: - Inject synthetic ToolCallPart and ToolReturnPart via message_history - Use RunOptions::skip_user_prompt (serdesAI fork) to suppress the trailing empty user prompt that was previously unavoidable - Added serdesAI fork as submodule pointing to feat/optional-prompt branch - Added [patch.crates-io] entries to build against the local fork Benefits: - Sub-agent sees correct tool-call context instead of a plain user message - Avoids extra API request caused by the mandatory trailing user prompt - Respects provider concurrency limits by eliminating redundant round-trips - Resolves message ordering issues on providers with strict alternation
Move orchestrator and reader agents from flat agents/ into agents/task-demo/, load them via add_file instead of add_directory, and document subfolder naming behaviour in file-reader.md. Changes: - Added HTML comment to file-reader.md documenting path-to-name mapping - Moved orchestrator.md and reader.md into agents/task-demo/ - Updated serdesai-task.rs to load from task-demo/ via add_file - Shortened agent prompt bodies to essentials Benefits: - Each example now owns its agent files independently - No namespace collisions between examples - Naming behaviour is self-documented in the example
Stop hiding the `task` tool when an agent is allowed to hand work to a callable helper agent. Changes: - made runtime tool filtering keep `task` when at least one allowed target exists - cleaned up old permission filtering helpers and tightened the task demo - added tests and short docs for default tool and Task permission behavior Benefits: - prevents agents from losing delegation even when a helper agent is allowed - makes permission behavior easier to understand and maintain
…nstead of user prompts" This reverts commit a7c0f96.
Replace `agent.run()` with `agent.run_stream()` so thinking, assistant text, tool calls, and task inputs are printed as they arrive. Each message is tagged with a stable `<mN:…>` id matching the request step, making it easy to see which thinking belongs to which turn. Changes: - Switched from `run()` to `run_stream()` for live output - Added streaming XML printer with open/close tag tracking via `OpenStreamTag` - Accumulate tool call args across deltas, render on `ToolCallComplete` - Render `TaskInput` in typed form; remove post-hoc tool return replay - Reordered file: `main` first, helpers in call order - Added comments where intent isn't obvious from code alone Benefits: - Can observe agent reasoning and activity as it happens - Stable message ids clearly associate thinking with the right turn - Shorter output by removing the redundant tool-return history section
5ae5f43 to
7d7c0cc
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
src/llm-coding-tools-serdesai/README.md (1)
112-147:⚠️ Potential issue | 🟡 MinorMention the extra
llm-coding-tools-models-devdependency in this section.This example imports
ModelsDevCatalogand usesload_result.catalog, but the surrounding text only calls outllm-coding-tools-agentsand a genericModelCatalog. Copy-pasting it still requiresllm-coding-tools-models-devinCargo.toml.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/llm-coding-tools-serdesai/README.md` around lines 112 - 147, The README example uses ModelsDevCatalog and load_result.catalog but doesn't mention the required crate; update the Task Tool section to explicitly note the extra dependency llm-coding-tools-models-dev and show adding it to Cargo.toml (or list it in the prerequisites), and adjust the imports/examples to reference ModelsDevCatalog so readers know to include llm-coding-tools-models-dev when using ModelsDevCatalog and load_result.catalog.
🧹 Nitpick comments (2)
src/llm-coding-tools-serdesai/src/agent_runtime/build.rs (1)
157-160: KeepPreparedBuilddepth-aware in one place.When delegation is blocked at
current_depth, this clears onlycallable_target_summaries.prepared.toolscan still containToolCatalogKind::Task, so the same build artifact says “Task exists” and “Task cannot be attached” at once.attach_standard_tools()masks it today, but that invariant is easy to break later. Filter the Task entry here too.♻️ Suggested adjustment
let mut prepared = prepare_build(runtime, name, model_catalog, credentials)?; if !runtime.task_settings().allows_delegation(current_depth) { + prepared.tools.retain(|entry| entry.kind != ToolCatalogKind::Task); prepared.callable_target_summaries.clear(); } Ok(prepared)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/llm-coding-tools-serdesai/src/agent_runtime/build.rs` around lines 157 - 160, The prepared build is depth-aware only for callable_target_summaries but not for prepared.tools, causing inconsistent state when delegation is disallowed; after calling prepare_build (symbol: prepare_build) and checking runtime.task_settings().allows_delegation(current_depth), filter out any ToolCatalogKind::Task entries from prepared.tools in the same branch where prepared.callable_target_summaries.clear() is invoked (reference symbols: prepared, PreparedBuild, prepared.tools, callable_target_summaries, ToolCatalogKind::Task) so the PreparedBuild consistently reflects that tasks cannot be attached; keep this filtering colocated with the existing delegation check to preserve the invariant and avoid relying on attach_standard_tools to mask the inconsistency.src/llm-coding-tools-agents/src/runtime/task.rs (1)
109-119: Skip the sort inresolve_allowed_tools().This branch only needs to know whether any callable task target exists, but
sorted_agents()allocates and sorts the whole catalog before a scan that may break on the first match. Iteratingruntime.catalog().iter()here keeps behavior unchanged and removes extra work from everyallowed_tools()call.♻️ Suggested simplification
- let agents = sorted_agents(runtime.catalog()); let task_rules = Ruleset::from_permission_config(&caller.permission); let has_explicit_task_permission = caller.permission.contains_key(tool_names::TASK); let mut task_is_callable = false; // Expose `task` only when at least one delegated target remains callable. - for target in agents { + for target in runtime.catalog().iter() { if target_is_callable(target, &task_rules, has_explicit_task_permission) { task_is_callable = true; break; } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/llm-coding-tools-agents/src/runtime/task.rs` around lines 109 - 119, The code currently calls sorted_agents(runtime.catalog()) in resolve_allowed_tools()/allowed_tools(), which allocates and sorts the entire catalog even though we only need to know if any callable target exists; change this to iterate runtime.catalog() directly (e.g., for target in runtime.catalog().iter()) so you avoid the allocation/sort, keeping the existing logic that builds task_rules via Ruleset::from_permission_config(&caller.permission) and checking targets with target_is_callable(...); ensure the loop variable types match the catalog iterator (no reliance on sorted_agents return type) and preserve the has_explicit_task_permission check and early break when a callable target is found.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/llm-coding-tools-agents/README.md`:
- Around line 67-68: Update the README comment that lists default tools to
explicitly include "task" (or alternately add a short note) so readers know the
default catalog carries Task as well; specifically modify the commented example
lines that show ".tools(...)" (the lines with "// .tools(my_custom_tools) //
optional; defaults to
read/write/edit/glob/grep/bash/webfetch/todoread/todowrite") to either append
"task" to the defaults or add a sentence that "task" is surfaced by default only
when at least one target is callable.
In `@src/llm-coding-tools-serdesai/examples/serdesai-task.rs`:
- Around line 161-179: log_xml() and close_stream_xml() produce mismatched XML
tags because the opening tag uses the message id in the element name (e.g.,
"<m{id}:{tag}>") but the closing tag only uses "{tag}"; update these functions
to ensure opening and closing names match consistently: either change the
opening tag to a stable element name (e.g., "<message tag=\"{tag}\"
id=\"{message_id}\">") and close with "</message>", or keep the current combined
name but include the full same name in the closing (e.g.,
"</m{message_id}:{tag}>"); also update close_stream_xml() to take and close the
exact same string stored in OpenStreamTag.tag so streamed output closes the
identical tag name.
---
Duplicate comments:
In `@src/llm-coding-tools-serdesai/README.md`:
- Around line 112-147: The README example uses ModelsDevCatalog and
load_result.catalog but doesn't mention the required crate; update the Task Tool
section to explicitly note the extra dependency llm-coding-tools-models-dev and
show adding it to Cargo.toml (or list it in the prerequisites), and adjust the
imports/examples to reference ModelsDevCatalog so readers know to include
llm-coding-tools-models-dev when using ModelsDevCatalog and load_result.catalog.
---
Nitpick comments:
In `@src/llm-coding-tools-agents/src/runtime/task.rs`:
- Around line 109-119: The code currently calls sorted_agents(runtime.catalog())
in resolve_allowed_tools()/allowed_tools(), which allocates and sorts the entire
catalog even though we only need to know if any callable target exists; change
this to iterate runtime.catalog() directly (e.g., for target in
runtime.catalog().iter()) so you avoid the allocation/sort, keeping the existing
logic that builds task_rules via
Ruleset::from_permission_config(&caller.permission) and checking targets with
target_is_callable(...); ensure the loop variable types match the catalog
iterator (no reliance on sorted_agents return type) and preserve the
has_explicit_task_permission check and early break when a callable target is
found.
In `@src/llm-coding-tools-serdesai/src/agent_runtime/build.rs`:
- Around line 157-160: The prepared build is depth-aware only for
callable_target_summaries but not for prepared.tools, causing inconsistent state
when delegation is disallowed; after calling prepare_build (symbol:
prepare_build) and checking
runtime.task_settings().allows_delegation(current_depth), filter out any
ToolCatalogKind::Task entries from prepared.tools in the same branch where
prepared.callable_target_summaries.clear() is invoked (reference symbols:
prepared, PreparedBuild, prepared.tools, callable_target_summaries,
ToolCatalogKind::Task) so the PreparedBuild consistently reflects that tasks
cannot be attached; keep this filtering colocated with the existing delegation
check to preserve the invariant and avoid relying on attach_standard_tools to
mask the inconsistency.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 8dfd71a5-f06e-4839-ae69-a015ee6eaac0
📒 Files selected for processing (12)
src/llm-coding-tools-agents/README.mdsrc/llm-coding-tools-agents/src/extensions.rssrc/llm-coding-tools-agents/src/runtime/mod.rssrc/llm-coding-tools-agents/src/runtime/state.rssrc/llm-coding-tools-agents/src/runtime/task.rssrc/llm-coding-tools-core/src/permissions.rssrc/llm-coding-tools-serdesai/README.mdsrc/llm-coding-tools-serdesai/examples/agents/task-demo/orchestrator.mdsrc/llm-coding-tools-serdesai/examples/agents/task-demo/reader.mdsrc/llm-coding-tools-serdesai/examples/serdesai-task.rssrc/llm-coding-tools-serdesai/src/agent_runtime/build.rssrc/llm-coding-tools-serdesai/src/agent_runtime/task.rs
💤 Files with no reviewable changes (1)
- src/llm-coding-tools-core/src/permissions.rs
✅ Files skipped from review due to trivial changes (1)
- src/llm-coding-tools-serdesai/examples/agents/task-demo/reader.md
🚧 Files skipped from review as they are similar to previous changes (2)
- src/llm-coding-tools-agents/src/runtime/state.rs
- src/llm-coding-tools-agents/src/runtime/mod.rs
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Build and Test (Async/Tokio) (ubuntu-latest, x86_64-unknown-linux-gnu, false)
- GitHub Check: Build and Test (Async/Tokio) (windows-latest, x86_64-pc-windows-msvc, false)
- GitHub Check: Build and Test (Async/Tokio) (macos-latest, aarch64-apple-darwin, false)
🧰 Additional context used
📓 Path-based instructions (1)
src/**/*.rs
📄 CodeRabbit inference engine (src/AGENTS.md)
src/**/*.rs: Preallocate collections when size is known or estimable usingString::with_capacity(estimated_len),Vec::with_capacity(count), orBufReader::with_capacity(size, reader)
Prefer&str/&[T]returns over owned types when lifetime allows
UseCow<'_, str>for conditional ownership (e.g.,String::from_utf8_lossy)
Use&'static strfor compile-time constant strings
Reuse buffers by calling.clear()and reusingVec/Stringinstead of reallocating
Use const generics for compile-time branching (e.g.,<const LINE_NUMBERS: bool>)
Use#[inline]on small, hot-path functions
Prefercoreoverstdwhere possible (e.g.,core::memoverstd::mem)
Usememchrcrate for fast byte searching over manual iteration
Keep modules under 500 lines (excluding tests); split if larger
Placeusestatements inside functions only for#[cfg]conditional compilation
Document public items with///and add examples in docs where helpful
Use//!for module-level documentation
Use [TypeName] rustdoc links instead of backticks in documentation
Files:
src/llm-coding-tools-serdesai/src/agent_runtime/task.rssrc/llm-coding-tools-serdesai/examples/serdesai-task.rssrc/llm-coding-tools-agents/src/extensions.rssrc/llm-coding-tools-agents/src/runtime/task.rssrc/llm-coding-tools-serdesai/src/agent_runtime/build.rs
🧠 Learnings (3)
📚 Learning: 2026-02-07T22:53:26.067Z
Learnt from: CR
Repo: Sewer56/llm-coding-tools PR: 0
File: src/AGENTS.md:0-0
Timestamp: 2026-02-07T22:53:26.067Z
Learning: Organize code with `llm-coding-tools-serdesai/` containing `src/absolute/`, `src/allowed/`, `src/schema.rs`, and `src/convert.rs` for serdesAI framework implementations
Applied to files:
src/llm-coding-tools-serdesai/README.mdsrc/llm-coding-tools-serdesai/src/agent_runtime/task.rssrc/llm-coding-tools-serdesai/examples/serdesai-task.rs
📚 Learning: 2026-02-07T22:53:26.067Z
Learnt from: CR
Repo: Sewer56/llm-coding-tools PR: 0
File: src/AGENTS.md:0-0
Timestamp: 2026-02-07T22:53:26.067Z
Learning: Organize code with `llm-coding-tools-core/` as framework-agnostic core library containing `src/tools/`, `src/path/`, `src/error.rs`, `src/output.rs`, and `src/util.rs`
Applied to files:
src/llm-coding-tools-serdesai/README.md
📚 Learning: 2026-02-07T22:53:26.067Z
Learnt from: CR
Repo: Sewer56/llm-coding-tools PR: 0
File: src/AGENTS.md:0-0
Timestamp: 2026-02-07T22:53:26.067Z
Learning: Applies to src/**/*.rs : Document public items with `///` and add examples in docs where helpful
Applied to files:
src/llm-coding-tools-serdesai/examples/serdesai-task.rs
🪛 GitHub Check: Build and Test (Blocking) (ubuntu-latest, x86_64-unknown-linux-gnu, false)
src/llm-coding-tools-serdesai/examples/serdesai-task.rs
[warning] 260-260:
Diff in /home/runner/work/llm-coding-tools/llm-coding-tools/src/llm-coding-tools-serdesai/examples/serdesai-task.rs
[warning] 152-152:
Diff in /home/runner/work/llm-coding-tools/llm-coding-tools/src/llm-coding-tools-serdesai/examples/serdesai-task.rs
[warning] 119-119:
Diff in /home/runner/work/llm-coding-tools/llm-coding-tools/src/llm-coding-tools-serdesai/examples/serdesai-task.rs
[warning] 13-13:
Diff in /home/runner/work/llm-coding-tools/llm-coding-tools/src/llm-coding-tools-serdesai/examples/serdesai-task.rs
The commented example omitted task from the default tool list despite it being included in DEFAULT_TOOLS.
The Task tool documentation stated subagent_type is required but the example invocation on the "When to Use" line omitted it.
The default_tools() bullet in the top-level doc comment listed only 8 tools but the catalog actually provides 10, including task.
…rget The validate_target method in the Task handler skips Ruleset filtering when caller.permission lacks an explicit task key, allowing delegation to non-Primary targets by default. This comment records that design decision to prevent confusion with Ruleset's default-deny documentation.
Add stateless Task tool for subagent delegation
TODO: Make task tool calls count as tool calls not user prompts.
janfeddersen-wq/serdesAI#33
Summary
build_with_taskmethod to build agents that can delegate to subagents, with shared credentials passed through