Skip to content

feat(agent): subturn#1636

Merged
yinwm merged 216 commits intosipeed:refactor/agentfrom
lppp04808:feat/subturn-poc
Mar 22, 2026
Merged

feat(agent): subturn#1636
yinwm merged 216 commits intosipeed:refactor/agentfrom
lppp04808:feat/subturn-poc

Conversation

@lppp04808
Copy link
Contributor

@lppp04808 lppp04808 commented Mar 16, 2026

📝 Description

This PR implements hierarchical agent execution (SubTurns) as designed in Issue #1316, enabling multi-agent coordination with complete lifecycle management, concurrency control, interrupt capabilities, and session state rollback.

Key Features

1. Core SubTurn Infrastructure

  • spawnSubTurn: Nested turn execution with configurable maxSubTurnDepth (3 levels)
  • Ephemeral sessions: Isolated child memory via ephemeralSessionStore — keeps parent session history clean
  • Context propagation: withTurnState/turnStateFromContext pass turn hierarchy through context
  • Panic recovery: Deferred recovery guarantees SubTurnEndEvent emission even on crashes

2. Integration with AgentLoop

  • Root turnState initialization: runAgentLoop creates root turnState, propagates via context, snapshots initial history length
  • Spawn Tool integration: SetSpawner callback wires Spawn Tool to spawnSubTurn
  • Result injection: dequeuePendingSubTurnResults polls child results and injects as [SubTurn Result] messages into parent conversation at two checkpoints (loop start + after each tool)
  • Automatic cleanup: rootTS.Finish() called on loop completion, cascading cancellation to all children

3. Concurrency Control (Semaphore)

  • Per-parent limit: maxConcurrentSubTurns = 5 — each parent can run max 5 concurrent children
  • Blocking behavior: 6th spawn blocks until a slot frees up
  • Context-aware: Respects context cancellation, won't block forever if parent aborts

4. Hard Abort Mechanism

  • HardAbort(sessionKey): Immediately cancels running agent loop for given session
  • Cascading cancellation: Triggers turnState.Finish(), propagating cancellation to all child SubTurns
  • Session state rollback: Truncates session history to initialHistoryLength, discarding all messages added during the aborted turn
  • Session tracking: activeTurnStates map tracks root turnState per session for abort lookup

5. Event System (Placeholder)

Four new event types for observability:

  • SubTurnSpawnEvent — child turn started
  • SubTurnResultDeliveredEvent — result delivered to parent
  • SubTurnEndEvent — child turn completed (success or error)
  • SubTurnOrphanResultEvent — late-arriving result after parent finished

Currently uses MockEventBus — real EventBus integration pending.

Test Coverage

  • 10 test cases covering:
    • Depth limits, session isolation, result delivery, orphan routing
    • Channel registration, concurrency semaphore
    • Hard abort cascading, session state rollback
  • All tests passing

Implementation Status (per Issue #1316)

Completed:

  • ✅ Tool refactoring (Spawn Tool → spawnSubTurn)
  • ✅ Root turnState initialization & context propagation
  • ✅ Concurrency semaphore (max 5 concurrent children per parent)
  • ✅ Hard abort with cascading cancellation
  • ✅ Session state rollback on hard abort

Pending:

  • ⚠️ Real EventBus integration (currently MockEventBus)

🗣️ Type of Change

  • 🐞 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 📖 Documentation update
  • ⚡ Code refactoring (no functional changes, no api changes)

🤖 AI Code Generation

  • 🤖 Fully AI-generated (100% AI, 0% Human)
  • 🛠️ Mostly AI-generated (AI draft, Human verified/modified)
  • 👨‍💻 Mostly Human-written (Human lead, AI assisted or none)

🔗 Related Issue

📚 Technical Context (Skip for Docs)

  • Reference URL:
  • Reasoning:

🧪 Test Environment

  • Hardware: PC
  • OS: Ubuntu 24.04
  • Model/Provider:
  • Channels:

📸 Evidence (Optional)

Click to view Logs/Screenshots

☑️ Checklist

  • My code/docs follow the style of this project.
  • I have performed a self-review of my own changes.
  • I have updated the documentation accordingly.

kiannidev and others added 30 commits March 12, 2026 02:22
When the claude CLI exits with a non-zero status, the previous error
handler only checked stderr. However, the CLI writes its output
(including error details) to stdout, especially when invoked with
--output-format json. This left the caller with only "exit status 1"
and no actionable information.

Now includes both stderr and stdout in the error message so the actual
failure reason is visible in logs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Add support for azure openai provider

* Add checks for deployment model name

* Apply suggestion from @Copilot

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Addressing @Copilot suggestion to remove the init() function which seemed redundant

* Fix readme

* Fix linting checks

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…tting

feat(logger): Custom console formatter for JSON and multiline strings
feat/sec add github's dependabot to scan the lib sec.
…token in the URL (sipeed#1563)

* fix: Use secure defaults for Pico channel setup and stop leaking the token in the URL

* fix: Derive default allow_origins from the setup request's Origin header instead of hardcoding localhost ports
)

Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.35.0 to 0.36.0.
- [Commits](golang/oauth2@v0.35.0...v0.36.0)

---
updated-dependencies:
- dependency-name: golang.org/x/oauth2
  dependency-version: 0.36.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…ed#1598)

Bumps [github.com/mymmrac/telego](https://github.com/mymmrac/telego) from 1.6.0 to 1.7.0.
- [Release notes](https://github.com/mymmrac/telego/releases)
- [Commits](mymmrac/telego@v1.6.0...v1.7.0)

---
updated-dependencies:
- dependency-name: github.com/mymmrac/telego
  dependency-version: 1.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…ipeed#1599)

Bumps [github.com/caarlos0/env/v11](https://github.com/caarlos0/env) from 11.3.1 to 11.4.0.
- [Release notes](https://github.com/caarlos0/env/releases)
- [Commits](caarlos0/env@v11.3.1...v11.4.0)

---
updated-dependencies:
- dependency-name: github.com/caarlos0/env/v11
  dependency-version: 11.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [github.com/anthropics/anthropic-sdk-go](https://github.com/anthropics/anthropic-sdk-go) from 1.22.1 to 1.26.0.
- [Release notes](https://github.com/anthropics/anthropic-sdk-go/releases)
- [Changelog](https://github.com/anthropics/anthropic-sdk-go/blob/main/CHANGELOG.md)
- [Commits](anthropics/anthropic-sdk-go@v1.22.1...v1.26.0)

---
updated-dependencies:
- dependency-name: github.com/anthropics/anthropic-sdk-go
  dependency-version: 1.26.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
….32 (sipeed#1603)

Bumps [github.com/github/copilot-sdk/go](https://github.com/github/copilot-sdk) from 0.1.23 to 0.1.32.
- [Release notes](https://github.com/github/copilot-sdk/releases)
- [Changelog](https://github.com/github/copilot-sdk/blob/main/CHANGELOG.md)
- [Commits](github/copilot-sdk@v0.1.23...v0.1.32)

---
updated-dependencies:
- dependency-name: github.com/github/copilot-sdk/go
  dependency-version: 0.1.32
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…d#1605)

Bumps [jotai](https://github.com/pmndrs/jotai) from 2.18.0 to 2.18.1.
- [Release notes](https://github.com/pmndrs/jotai/releases)
- [Commits](pmndrs/jotai@v2.18.0...v2.18.1)

---
updated-dependencies:
- dependency-name: jotai
  dependency-version: 2.18.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
)

Bumps [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react) from 5.1.4 to 5.2.0.
- [Release notes](https://github.com/vitejs/vite-plugin-react/releases)
- [Changelog](https://github.com/vitejs/vite-plugin-react/blob/plugin-react@5.2.0/packages/plugin-react/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite-plugin-react/commits/plugin-react@5.2.0/packages/plugin-react)

---
updated-dependencies:
- dependency-name: "@vitejs/plugin-react"
  dependency-version: 5.2.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
sipeed#1607)

Bumps [react-i18next](https://github.com/i18next/react-i18next) from 16.5.4 to 16.5.8.
- [Changelog](https://github.com/i18next/react-i18next/blob/master/CHANGELOG.md)
- [Commits](i18next/react-i18next@v16.5.4...v16.5.8)

---
updated-dependencies:
- dependency-name: react-i18next
  dependency-version: 16.5.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…eed#1608)

Bumps [dayjs](https://github.com/iamkun/dayjs) from 1.11.19 to 1.11.20.
- [Release notes](https://github.com/iamkun/dayjs/releases)
- [Changelog](https://github.com/iamkun/dayjs/blob/dev/CHANGELOG.md)
- [Commits](iamkun/dayjs@v1.11.19...v1.11.20)

---
updated-dependencies:
- dependency-name: dayjs
  dependency-version: 1.11.20
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [@tanstack/react-router](https://github.com/TanStack/router/tree/HEAD/packages/react-router) from 1.163.3 to 1.167.0.
- [Release notes](https://github.com/TanStack/router/releases)
- [Changelog](https://github.com/TanStack/router/blob/main/packages/react-router/CHANGELOG.md)
- [Commits](https://github.com/TanStack/router/commits/@tanstack/react-router@1.167.0/packages/react-router)

---
updated-dependencies:
- dependency-name: "@tanstack/react-router"
  dependency-version: 1.167.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
lppp04808 and others added 20 commits March 21, 2026 17:12
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Add agent-browser skill to the default workspace with complete CLI
reference for browser automation via Chrome/Chromium CDP. The skill
includes a runtime guard that checks for the binary before use.

Add Dockerfile.heavy — a batteries-included container image with:
- Node.js 24 + npm
- Python 3 + pip + uv
- Chromium + Playwright (for agent-browser)
- agent-browser CLI pre-installed
- Non-root picoclaw user (UID/GID 1000)
- Default workspace with all skills
- Persistent workspace volume

This complements the existing minimal Dockerfile and Dockerfile.full
for deployments that need browser automation and rich tool support.
…PTY support (sipeed#1752)

- Unified exec tool with actions: run/list/poll/read/write/send-keys/kill
- PTY support using creack/pty library
- Process session management with background execution
- Process group kill for cleaning up child processes
- Session cleanup: 30-minute TTL for old sessions
- Output buffer: 100MB limit with truncation

Actions:
- run: execute command (sync or background)
- list: list all sessions
- poll: check session status
- read: read session output
- write: send input to session stdin
- send-keys: send special keys (up, down, ctrl-c, enter, etc.)
- kill: terminate session

Tests:
- PTY: allowed commands, write/read, poll, kill, process group kill
- Non-PTY: background execution, list, read, write, poll, kill, process group kill
- Session management: add/get/remove/list/cleanup
…-enhancement

Revert "feat(tools): add exec tool enhancement with background execution and PTY support"
…skill-heavy-dockerfile

feat: add agent-browser skill and Dockerfile.heavy
…nore

chore: Ignore the `docker/data` directory.
…validation

fix(identity): support negative integers in isNumeric for Telegram group IDs
…mplate-idle

fix(heartbeat): ignore untouched default template
docs: clean up README and update QRCode
feat(logging): add configurability for log levels preference
@alexhoshina alexhoshina changed the base branch from main to refactor/agent March 22, 2026 06:59
@alexhoshina alexhoshina changed the base branch from refactor/agent to main March 22, 2026 06:59
@lppp04808 lppp04808 changed the base branch from main to refactor/agent March 22, 2026 11:22
…bus exit

- spawnSubTurn: set result=nil on panic instead of constructing a non-nil ToolResult
- HardAbort: roll back session history to initialHistoryLength after Finish()
- drainBusToSteering: switch to non-blocking reads after first message so function
  returns promptly when the inbound channel is empty
- remove obsolete documentation files
@yinwm yinwm merged commit 729a878 into sipeed:refactor/agent Mar 22, 2026
4 checks passed
@yinwm
Copy link
Collaborator

yinwm commented Mar 22, 2026

@lppp04808 thanks for the pr

@sipeed-bot
Copy link

sipeed-bot bot commented Mar 25, 2026

@lppp04808 This is a substantial contribution! Hierarchical agent execution with SubTurns, concurrency control, and session state rollback is a big step forward for multi-agent coordination in PicoClaw.

We have a PicoClaw Dev Group on Discord for contributors to connect. If you are interested, send an email to support@sipeed.com with the subject [Join PicoClaw Dev Group] + Your GitHub account and we will send you the invite link!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.