Skip to content

Commit 33c0e56

Browse files
committed
feat: add automatic subagent parallelization
Prepare v3.1.0 release with automatic subagent delegation, native .a3s/agents loading, SDK API alignment, release version updates, and expanded unit/integration coverage.
1 parent 529986f commit 33c0e56

48 files changed

Lines changed: 3952 additions & 182 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,54 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [3.1.0] - 2026-05-23
9+
10+
### Added
11+
12+
- Added Claude Code-style automatic subagent delegation. When a request matches
13+
multiple independent specialists, the runtime can pre-run those child agents
14+
through one bounded `parallel_task` call and feed the gathered context back
15+
into the main turn.
16+
- Added `auto_delegation` configuration and session overrides, including the
17+
global `auto_parallel` kill switch. Setting `auto_parallel = false` disables
18+
automatic parallel child-agent fan-out while keeping manual `parallel_task`
19+
available.
20+
- Added `max_parallel_tasks` as the shared sibling fan-out limit for
21+
`parallel_task`, delegated plan waves, and safe parallel write batches.
22+
- Added a reusable ordered parallel executor so concurrent child results remain
23+
deterministic and individual task failures are isolated.
24+
- Added native `.a3s/agents` and `~/.a3s/agents` subagent discovery with
25+
recursive loading. `.claude/agents` remains a compatibility source, but
26+
`.a3s/agents` wins when the same agent name appears in both locations.
27+
- Added Claude-style markdown agent compatibility for `tools`,
28+
`allowedTools`, and `disallowedTools` frontmatter. `tools` behaves as an
29+
allowlist and `disallowedTools` is a denylist that takes precedence.
30+
- Added direct worker/subagent APIs across Rust, Node.js, and Python:
31+
`WorkerAgentSpec`, `AgentDefinition`, `session_for_worker`, live worker
32+
registration, and `task` / `parallel_task` helpers.
33+
- Added real-provider smoke coverage for automatic parallel delegation and
34+
built-in subagent execution using `.a3s/config.acl`.
35+
36+
### Changed
37+
38+
- Aligned built-in subagent names and aliases with Claude Code conventions:
39+
`general-purpose` aliases to `general`; `verify` / `verifier` alias to
40+
`verification`; `code-review` / `reviewer` alias to `review`.
41+
- Tightened built-in subagent permission boundaries. Read-only and review-style
42+
agents now default-deny undeclared tools, and all built-ins deny recursive
43+
`task` / `parallel_task` delegation to prevent unbounded nesting.
44+
- Collapsed independent delegated plan waves into a single `parallel_task`
45+
operation where possible, rather than launching serial sibling `task` calls.
46+
- Updated Node and Python SDK documentation to prefer the single delegation
47+
surface backed by the core `task` and `parallel_task` tools.
48+
49+
### Fixed
50+
51+
- Fixed release helper version checks so they no longer reference the removed
52+
`cli/` package.
53+
- Fixed explicit subagent trigger parsing so normal phrases such as "use the
54+
plan" are not mistaken for a `plan` subagent request.
55+
856
## [3.0.0] - 2026-05-20
957

1058
### Added (Phase 8 — typed-error SDK alignment)

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ Create `agent.acl`:
7575

7676
```acl
7777
default_model = "anthropic/claude-sonnet-4-20250514"
78+
max_parallel_tasks = 8
79+
auto_parallel = false
7880
7981
providers "anthropic" {
8082
apiKey = env("ANTHROPIC_API_KEY")
@@ -1113,6 +1115,43 @@ Core delegation primitives:
11131115
- `task` — run one focused delegated child run
11141116
- `parallel_task` — run independent delegated child runs concurrently
11151117

1118+
Built-in subagents are available through these primitives and through automatic
1119+
delegation:
1120+
1121+
- `explore` — read-only codebase search and inspection
1122+
- `plan` — read-only implementation planning
1123+
- `general` / `general-purpose` — multi-step implementation work
1124+
- `verification` — adversarial checks and regression validation
1125+
- `review` — code review findings
1126+
1127+
Automatic delegation can trigger from high-confidence task descriptions, from
1128+
Claude Code-style proactive agent descriptions, or explicitly with mentions such
1129+
as `@general-purpose`, `@agent-plan`, `use the review subagent`, `delegate to
1130+
verification`, or `ask docs-auditor`.
1131+
1132+
Custom agents are loaded recursively from configured `agent_dirs`, from
1133+
`./.a3s/agents`, and from `~/.a3s/agents`. The Claude-compatible
1134+
`./.claude/agents` and `~/.claude/agents` paths are still read as migration
1135+
sources, but `.a3s/agents` is the native A3S location and wins for same-name
1136+
agents. Markdown agent files support Claude-style frontmatter:
1137+
1138+
```markdown
1139+
---
1140+
name: docs-auditor
1141+
description: Use proactively after documentation changes
1142+
tools: Read, Grep, Glob
1143+
disallowedTools:
1144+
- Write
1145+
- Bash(rm:*)
1146+
---
1147+
1148+
Audit docs for drift, broken examples, and unclear migration notes.
1149+
```
1150+
1151+
The `tools` field is treated as an allowlist. `disallowedTools` is applied as a
1152+
denylist and wins over allowed tools. Model routing fields are intentionally not
1153+
part of this compatibility layer.
1154+
11161155
The older model-visible team shortcut and duplicate lifecycle control-plane API
11171156
are no longer part of the public surface. Multi-agent work enters through the
11181157
delegation core.
@@ -1271,6 +1310,8 @@ blocks such as `providers "anthropic" { ... }`.
12711310

12721311
```acl
12731312
default_model = "anthropic/claude-sonnet-4-20250514"
1313+
max_parallel_tasks = 8
1314+
auto_parallel = false
12741315
12751316
providers "anthropic" {
12761317
apiKey = env("ANTHROPIC_API_KEY")
@@ -1286,6 +1327,13 @@ providers "anthropic" {
12861327
skill_dirs = ["./skills"]
12871328
mcp_servers = []
12881329
1330+
auto_delegation {
1331+
enabled = false
1332+
auto_parallel = false
1333+
min_confidence = 0.72
1334+
max_tasks = 4
1335+
}
1336+
12891337
ahp = {
12901338
enabled = true
12911339
url = "http://harness:8080/ahp"
@@ -1297,6 +1345,12 @@ Model token limits use the `limit = { context = ..., output = ... }` object as t
12971345
The flat `maxTokens` and `contextTokens` fields are accepted only as deprecated
12981346
migration aliases and emit warnings.
12991347

1348+
`max_parallel_tasks` bounds sibling fan-out for `parallel_task`, plan waves, and
1349+
safe parallel write batches.
1350+
`auto_delegation.enabled` controls Claude Code-style automatic subagent
1351+
delegation. `auto_parallel = false` is a global kill switch for automatic
1352+
parallel child-agent fan-out; manual `parallel_task` remains available.
1353+
13001354
---
13011355

13021356
## Development

core/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "a3s-code-core"
3-
version = "3.0.0"
3+
version = "3.1.0"
44
edition = "2021"
55
authors = ["A3S Lab Team"]
66
license = "MIT"

core/src/agent.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@ use crate::planning::{AgentGoal, ExecutionPlan, TaskStatus};
2020
use crate::prompts::{PlanningMode, SystemPromptSlots};
2121
use crate::queue::{SessionCommand, SessionQueueConfig};
2222
use crate::session_lane_queue::SessionLaneQueue;
23+
use crate::subagent::AgentRegistry;
2324
use crate::tools::{ToolContext, ToolExecutor};
2425
use anyhow::Result;
2526
use async_trait::async_trait;
2627
use serde::{Deserialize, Serialize};
2728
use serde_json::Value;
2829
use std::sync::Arc;
2930

31+
mod auto_delegation;
3032
mod completion_runtime;
3133
mod context_perception;
3234
mod execution_entry;
@@ -54,6 +56,7 @@ mod turn_context;
5456

5557
/// Maximum number of tool execution rounds before stopping
5658
pub(crate) const MAX_TOOL_ROUNDS: usize = 50;
59+
pub(crate) const DEFAULT_MAX_PARALLEL_TASKS: usize = 8;
5760

5861
/// Internal agent loop configuration.
5962
#[derive(Clone)]
@@ -100,6 +103,13 @@ pub(crate) struct AgentConfig {
100103
/// A timeout produces an error result sent back to the LLM rather than
101104
/// crashing the session.
102105
pub tool_timeout_ms: Option<u64>,
106+
/// Maximum number of sibling branches/tools to run concurrently in bounded
107+
/// parallel fan-out paths.
108+
pub max_parallel_tasks: usize,
109+
/// Runtime-driven automatic child-agent delegation.
110+
pub auto_delegation: crate::config::AutoDelegationConfig,
111+
/// Available child agents for automatic delegation.
112+
pub agent_registry: Option<Arc<AgentRegistry>>,
103113
/// Circuit-breaker threshold: max consecutive LLM API failures before
104114
/// aborting (default: 3).
105115
///
@@ -165,6 +175,12 @@ impl std::fmt::Debug for AgentConfig {
165175
)
166176
.field("max_parse_retries", &self.max_parse_retries)
167177
.field("tool_timeout_ms", &self.tool_timeout_ms)
178+
.field("max_parallel_tasks", &self.max_parallel_tasks)
179+
.field("auto_delegation", &self.auto_delegation)
180+
.field(
181+
"agent_registry",
182+
&self.agent_registry.as_ref().map(|registry| registry.len()),
183+
)
168184
.field("circuit_breaker_threshold", &self.circuit_breaker_threshold)
169185
.field(
170186
"duplicate_tool_call_threshold",
@@ -199,6 +215,9 @@ impl Default for AgentConfig {
199215
skill_registry: Some(Arc::new(crate::skills::SkillRegistry::with_builtins())),
200216
max_parse_retries: 2,
201217
tool_timeout_ms: None,
218+
max_parallel_tasks: DEFAULT_MAX_PARALLEL_TASKS,
219+
auto_delegation: crate::config::AutoDelegationConfig::default(),
220+
agent_registry: None,
202221
circuit_breaker_threshold: 3,
203222
duplicate_tool_call_threshold: 3,
204223
auto_compact: false,

0 commit comments

Comments
 (0)