@@ -287,27 +287,104 @@ When configured via `AgentConfig::tool_index`, the agent loop extracts the last
287287
288288### 👥 Agent Teams (Multi-Agent Coordination)
289289
290- Peer-to-peer multi-agent collaboration through a shared task board and message passing :
290+ Automated Lead → Worker → Reviewer workflows with real LLM execution :
291291
292292``` rust
293- use a3s_code_core :: agent_teams :: {AgentTeam , TeamConfig , TeamRole };
293+ use a3s_code_core :: {Agent , SessionOptions , agent_teams :: {AgentTeam , TeamConfig , TeamRole , TeamRunner }};
294+
295+ let agent = Agent :: new (" agent.hcl" ). await ? ;
294296
295297let mut team = AgentTeam :: new (" refactor-auth" , TeamConfig :: default ());
296298team . add_member (" lead" , TeamRole :: Lead );
297299team . add_member (" worker-1" , TeamRole :: Worker );
298300team . add_member (" reviewer" , TeamRole :: Reviewer );
299301
300- // Post a task to the board
301- team . task_board (). post (" Refactor auth module" , " lead" , None );
302+ let mut runner = TeamRunner :: new (team );
303+ runner . bind_session (" lead" , Arc :: new (agent . session (" ." , None )? ))? ;
304+ runner . bind_session (" worker-1" , Arc :: new (agent . session (" ." , None )? ))? ;
305+ runner . bind_session (" reviewer" , Arc :: new (agent . session (" ." , None )? ))? ;
306+
307+ let result = runner . run_until_done (" Refactor auth module to use JWT" ). await ? ;
308+ println! (" Done: {} tasks, {} rejected, {} rounds" ,
309+ result . done_tasks. len (), result . rejected_tasks. len (), result . rounds);
310+ ```
311+
312+ ** How it works:**
313+ 1 . ** Lead** decomposes the goal into a JSON task list via LLM
314+ 2 . ** Workers** concurrently claim and execute tasks (each via its own ` AgentSession ` )
315+ 3 . ** Reviewer** inspects completed work — APPROVED moves the task to Done, REJECTED re-queues it for retry
316+ 4 . Loop continues until all tasks are Done or ` max_rounds ` is reached
317+
318+ ** Low-level coordination API** (for custom orchestrators):
319+
320+ ``` rust
321+ // Post, claim, complete manually (no LLM required)
322+ team . task_board (). post (" Refactor auth" , " lead" , None );
323+ let task = team . task_board (). claim (" worker-1" ). unwrap ();
324+ team . task_board (). complete (& task . id, " Refactored to JWT" );
325+ team . task_board (). approve (& task . id);
326+
327+ // Peer messaging
328+ team . send_message (" lead" , " worker-1" , " Focus on the refresh token flow" , None ). await ;
329+ let mut rx = team . take_receiver (" worker-1" ). unwrap ();
330+ while let Some (msg ) = rx . recv (). await { println! (" {}: {}" , msg . from, msg . content); }
331+ ```
332+
333+ <details >
334+ <summary ><b >TypeScript</b ></summary >
302335
303- // Worker claims and works on it
304- let task = team . task_board (). claim (" worker-1" );
336+ ``` typescript
337+ import { Agent , Team , TeamRunner , TeamConfig } from ' @a3s-lab/code' ;
338+
339+ const agent = await Agent .create (' agent.hcl' );
305340
306- // Complete → Review → Approve/Reject workflow
307- team . task_board (). complete (" task-1" , " Refactored to JWT" );
308- team . task_board (). approve (" task-1" );
341+ const config: TeamConfig = { maxTasks: 50 , channelBuffer: 128 , maxRounds: 10 , pollIntervalMs: 200 };
342+ const team = new Team (' refactor-auth' , config );
343+ team .addMember (' lead' , ' lead' );
344+ team .addMember (' worker-1' , ' worker' );
345+ team .addMember (' reviewer' , ' reviewer' );
346+
347+ const runner = new TeamRunner (team );
348+ runner .bindSession (' lead' , agent .session (' .' ));
349+ runner .bindSession (' worker-1' , agent .session (' .' ));
350+ runner .bindSession (' reviewer' , agent .session (' .' ));
351+
352+ const result = await runner .runUntilDone (' Refactor auth module to use JWT' );
353+ console .log (` Done: ${result .doneTasks .length } tasks, ${result .rounds } rounds ` );
354+ for (const task of result .doneTasks ) {
355+ console .log (` [${task .id }] ${task .description }\n → ${task .result } ` );
356+ }
309357```
310358
359+ </details >
360+
361+ <details >
362+ <summary ><b >Python</b ></summary >
363+
364+ ``` python
365+ from a3s_code import Agent, Team, TeamRunner, TeamConfig
366+
367+ agent = Agent.create(" agent.hcl" )
368+
369+ config = TeamConfig(max_rounds = 10 , poll_interval_ms = 200 )
370+ team = Team(" refactor-auth" , config)
371+ team.add_member(" lead" , " lead" )
372+ team.add_member(" worker-1" , " worker" )
373+ team.add_member(" reviewer" , " reviewer" )
374+
375+ runner = TeamRunner(team)
376+ runner.bind_session(" lead" , agent.session(" ." ))
377+ runner.bind_session(" worker-1" , agent.session(" ." ))
378+ runner.bind_session(" reviewer" , agent.session(" ." ))
379+
380+ result = runner.run_until_done(" Refactor auth module to use JWT" )
381+ print (f " Done: { len (result.done_tasks)} tasks, { result.rounds} rounds " )
382+ for task in result.done_tasks:
383+ print (f " [ { task.id} ] { task.description} \n → { task.result} " )
384+ ```
385+
386+ </details >
387+
311388Supports Lead/Worker/Reviewer roles, ` mpsc ` peer messaging, broadcast, and a full task lifecycle (Open → InProgress → InReview → Done/Rejected).
312389
313390---
@@ -534,6 +611,11 @@ AgentTeam (multi-agent coordination)
534611 ├── TeamTaskBoard (post → claim → complete → review → approve/reject)
535612 ├── TeamMember[] (Lead, Worker, Reviewer roles)
536613 └── mpsc channels (peer-to-peer messaging + broadcast)
614+
615+ TeamRunner (LLM-integrated orchestrator)
616+ ├── Lead → decomposes goal into JSON task list
617+ ├── Workers → concurrently claim + execute tasks via AgentSession
618+ └── Reviewer → approve (Done) or reject (re-queued for retry)
537619```
538620
539621---
@@ -705,6 +787,39 @@ SessionOptions::new()
705787 . with_hook_engine (hooks )
706788```
707789
790+ ### Python SDK — Agent Teams
791+
792+ ``` python
793+ from a3s_code import Agent, Team, TeamRunner, TeamConfig, TeamTaskBoard
794+
795+ # Build team
796+ config = TeamConfig(max_tasks = 50 , max_rounds = 10 , poll_interval_ms = 200 )
797+ team = Team(" my-team" , config)
798+ team.add_member(" lead" , " lead" ) # role: "lead" | "worker" | "reviewer"
799+ team.add_member(" worker-1" , " worker" )
800+ team.add_member(" reviewer" , " reviewer" )
801+
802+ # Bind sessions and run
803+ runner = TeamRunner(team) # consumes the team
804+ runner.bind_session(" lead" , agent.session(" ." ))
805+ result = runner.run_until_done(" Build the feature" )
806+
807+ # Inspect results
808+ result.done_tasks # List[TeamTask]
809+ result.rejected_tasks # List[TeamTask] (did not pass review after max_rounds)
810+ result.rounds # int
811+
812+ # Direct board access
813+ board = runner.task_board()
814+ board.post(" Fix lint" , " lead" )
815+ board.claim(" worker-1" ) # → TeamTask | None
816+ board.complete(task_id, " Fixed" )
817+ board.approve(task_id)
818+ board.reject(task_id)
819+ tasks = board.by_status(" done" ) # "open"|"in_progress"|"in_review"|"done"|"rejected"
820+ (open , prog, rev, done, rej) = board.stats()
821+ ```
822+
708823### Python SDK
709824
710825``` python
@@ -750,6 +865,39 @@ session.save()
750865resumed = agent.resume_session(session.session_id, opts)
751866```
752867
868+ ### Node.js SDK — Agent Teams
869+
870+ ``` typescript
871+ import { Agent , Team , TeamRunner , TeamConfig , TeamTaskBoard } from ' @a3s-lab/code' ;
872+
873+ // Build team
874+ const config: TeamConfig = { maxTasks: 50 , channelBuffer: 128 , maxRounds: 10 , pollIntervalMs: 200 };
875+ const team = new Team (' my-team' , config );
876+ team .addMember (' lead' , ' lead' ); // role: "lead" | "worker" | "reviewer"
877+ team .addMember (' worker-1' , ' worker' );
878+ team .addMember (' reviewer' , ' reviewer' );
879+
880+ // Bind sessions and run
881+ const runner = new TeamRunner (team ); // consumes the team
882+ runner .bindSession (' lead' , agent .session (' .' ));
883+ const result = await runner .runUntilDone (' Build the feature' );
884+
885+ // Inspect results
886+ result .doneTasks // TeamTask[]
887+ result .rejectedTasks // TeamTask[] (did not pass review after maxRounds)
888+ result .rounds // number
889+
890+ // Direct board access
891+ const board = runner .taskBoard ();
892+ board .post (' Fix lint' , ' lead' );
893+ board .claim (' worker-1' ); // → TeamTask | null
894+ board .complete (taskId , ' Fixed' );
895+ board .approve (taskId );
896+ board .reject (taskId );
897+ const tasks = await board .byStatus (' done' ); // "open"|"in_progress"|"in_review"|"done"|"rejected"
898+ const stats = board .stats (); // { open, inProgress, inReview, done, rejected, total }
899+ ```
900+
753901### Node.js SDK
754902
755903``` typescript
@@ -833,10 +981,12 @@ cargo run --example 02_streaming
833981| Python | ` sdk/python/examples/advanced_features_demo.py ` | Direct tools, hooks, queue/lanes, security, resilience, memory |
834982| Python | ` sdk/python/examples/test_git_worktree.py ` | Git worktree tool: direct calls + LLM-driven |
835983| Python | ` sdk/python/examples/test_prompt_slots.py ` | Prompt slots: role, guidelines, response style, extra |
984+ | Python | ` sdk/python/examples/test_agent_teams.py ` | Multi-agent teams: TeamRunner, Lead/Worker/Reviewer workflow |
836985| Node.js | ` sdk/node/examples/agentic_loop_demo.js ` | Basic send, streaming, multi-turn, planning, skills, security |
837986| Node.js | ` sdk/node/examples/advanced_features_demo.js ` | Direct tools, hooks, queue/lanes, security, resilience, memory |
838987| Node.js | ` sdk/node/examples/test_git_worktree.js ` | Git worktree tool: direct calls + LLM-driven |
839988| Node.js | ` sdk/node/examples/test_prompt_slots.js ` | Prompt slots: role, guidelines, response style, extra |
989+ | Node.js | ` sdk/node/examples/test_agent_teams.js ` | Multi-agent teams: TeamRunner, Lead/Worker/Reviewer workflow |
840990
841991### Integration & Feature Tests
842992
0 commit comments