Skip to content

feat: add agent team observation support#1

Merged
teng-lin merged 1 commit intomainfrom
feature/agent-teams
Feb 16, 2026
Merged

feat: add agent team observation support#1
teng-lin merged 1 commit intomainfrom
feature/agent-teams

Conversation

@teng-lin
Copy link
Copy Markdown
Owner

Summary

  • Implement observation-only team state tracking for Claude Code's agent teams protocol (experimental, v2.1.32+)
  • Derive TeamState from the SDK message stream using a pure reducer pipeline: tool recognizer → correlation buffer → state reducer
  • Add teams: boolean capability flag to BackendCapabilities (sdk-url: true, agent-sdk: true, acp/codex: false)
  • Emit 8 typed bridge events for team lifecycle changes (created/deleted, member joined/idle/shutdown, task created/claimed/completed)

Architecture

SDK stream → recognizeTeamToolUses() → correlationBuffer.onToolUse/onToolResult()
           → reduceTeamState() → emitTeamEvents() → BridgeEventMap
  • Observation-only — derives state from messages, never reads ~/.claude/teams/ filesystem
  • Pure reducers — no side effects, matches existing state-reducer.ts pattern
  • Idempotent — all mutations check for existence before insert (safe for reconnection replay)
  • Per-session correlation buffers — prevents cross-session state corruption
  • Backward compatibleagents: string[] field populated from team.members

New files

File LOC Purpose
core/types/team-types.ts 164 TeamState, TeamMember, TeamTask, 8 TeamEvent types, type guards
core/team-tool-recognizer.ts 142 Recognizes 7 team tools with compound discriminator for Task
core/team-tool-correlation.ts 90 Buffers tool_use↔tool_result pairs with 30s TTL
core/team-state-reducer.ts 261 Pure reducer: correlated tool pairs → TeamState

Modified files (24)

  • session-bridge.ts — per-session correlation buffer, team event diffing on both CLI and unified paths
  • state-reducer.ts — wired team reducer pipeline into message processing
  • unified-message.ts — 3 new message types: team_message, team_task_update, team_state_change
  • backend-adapter.tsteams capability flag
  • extensions.tsTeamObserver interface (observation-only, no send methods)
  • session-state.tsteam?: TeamState field
  • events.ts — 8 team bridge events in BridgeEventMap
  • All 4 adapters — teams capability declaration

Test plan

  • 189 new team-specific tests across 6 test files
  • All 1292 tests pass (0 regressions from baseline 1103)
  • Table-driven tests for all 7 recognized tools
  • Correlation buffer: TTL expiry, is_error handling, out-of-order
  • Reducer idempotency: duplicate creates, updates, spawns
  • Full lifecycle integration: create → member → task → complete → delete
  • Bridge event emission: diffing members and tasks
  • Backward compat: agents[] populated from team.members
  • Biome lint clean, no non-null assertions

Review process

Implementation plan was reviewed by a 3-agent team (architect, protocol-reviewer, devil-advocate) that identified 4 CRITICAL, 5 HIGH, 7 MEDIUM, and 5 LOW issues. All CRITICAL and HIGH findings were resolved in a plan revision before implementation began. Code was polished via a 3-stage pipeline (simplification, dual Claude+Gemini review, deep analysis) that caught and fixed 2 additional bugs (singleton buffer, missing CLI path events).

Implement observation-only team state tracking for Claude Code's agent
teams protocol. Derives TeamState from the SDK message stream using a
pure reducer pipeline: recognizer → correlation buffer → state reducer.

Key components:
- team-types.ts: TeamState, TeamMember, TeamTask, 8 TeamEvent types
- team-tool-recognizer.ts: recognizes 7 team tools with compound
  discriminator for Task tool (requires both team_name and name)
- team-tool-correlation.ts: buffers tool_use↔tool_result pairs (30s TTL)
- team-state-reducer.ts: idempotent pure reducer for team state
- session-bridge.ts: per-session correlation buffers, team event emission
- events.ts: 8 bridge events (team lifecycle, members, tasks)

All reducer operations are idempotent for reconnection replay safety.
Backward compatible: agents[] field populated from team.members.

189 new tests, 0 regressions.
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @teng-lin, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request integrates comprehensive agent team observation capabilities into BeamCode. It establishes a robust, observation-only mechanism to track the dynamic state of agent teams, their members, and tasks by processing the SDK message stream. The design emphasizes pure functions, idempotency, and resilience against context compression, while also providing clear eventing for consumers and maintaining compatibility with existing structures.

Highlights

  • Agent Team Observation: Implemented observation-only support for Claude Code's agent teams protocol, allowing BeamCode to track team state, members, and tasks without direct filesystem access.
  • Pure Reducer Pipeline: Introduced a pure reducer pipeline (tool recognizer → correlation buffer → state reducer) to derive TeamState from the SDK message stream, ensuring predictable state management.
  • Backend Capabilities: Added a teams: boolean capability flag to BackendCapabilities, indicating which adapters support agent team coordination (SdkUrl and AgentSdk are true, ACP and Codex are false).
  • Team Lifecycle Events: Emitted 8 new typed bridge events for key team lifecycle changes, including team creation/deletion, member status updates, and task management.
  • Backward Compatibility & Persistence: Maintained backward compatibility for the agents: string[] field by populating it from team.members, and ensured TeamState persistence to session storage to mitigate context compression data loss.
Changelog
  • docs/plans/agent-teams-implementation-plan.md
    • Added a detailed implementation plan for agent team support.
  • docs/plans/agent-teams-plan-review.md
    • Added a consolidated review document for the agent teams plan, detailing critical, high, medium, and low issues and their resolutions.
  • src/adapters/acp/acp-adapter.test.ts
    • Updated AcpAdapter capabilities to explicitly set teams: false.
  • src/adapters/acp/acp-adapter.ts
    • Updated AcpAdapter capabilities to explicitly set teams: false.
  • src/adapters/agent-sdk/agent-sdk-adapter.test.ts
    • Updated AgentSdkAdapter capabilities to explicitly set teams: true.
  • src/adapters/agent-sdk/agent-sdk-adapter.ts
    • Updated AgentSdkAdapter capabilities to explicitly set teams: true.
  • src/adapters/codex/codex-adapter.test.ts
    • Updated CodexAdapter capabilities to explicitly set teams: false.
  • src/adapters/codex/codex-adapter.ts
    • Updated CodexAdapter capabilities to explicitly set teams: false.
  • src/adapters/codex/codex-compliance.test.ts
    • Updated ComplianceCodexAdapter capabilities to explicitly set teams: false.
  • src/adapters/sdk-url/sdk-url-adapter.ts
    • Updated SdkUrlAdapter capabilities to explicitly set teams: true.
  • src/adapters/sdk-url/state-reducer.ts
    • Modified the reduce function to integrate team tool processing, including buffering and state reduction.
    • Added a new reduceTeamTools function to handle team-related tool_use and tool_result blocks.
  • src/adapters/sdk-url/team-state-integration.test.ts
    • Added new tests for the sdk-url state reducer's integration with team state management.
  • src/core/index.ts
    • Exported new team-related types and type guards.
  • src/core/interfaces/backend-adapter-compliance.test.ts
    • Updated EchoAdapter capabilities to explicitly set teams: false.
  • src/core/interfaces/backend-adapter-compliance.ts
    • Added an assertion to check for the teams capability in compliance tests.
  • src/core/interfaces/backend-adapter.test.ts
    • Updated MockAdapter capabilities to explicitly set teams: false.
  • src/core/interfaces/backend-adapter.ts
    • Added a teams: boolean field to the BackendCapabilities interface.
  • src/core/interfaces/extensions.ts
    • Added the TeamObserver interface for observing team coordination events.
  • src/core/session-bridge-adapter.test.ts
    • Updated MockBackendAdapter and ErrorBackendAdapter capabilities to explicitly set teams: false.
  • src/core/session-bridge.ts
    • Integrated team correlation buffer into the session bridge's message routing.
    • Integrated team event emission into the session bridge's message routing.
  • src/core/team-events.test.ts
    • Added new tests for team event emission from the session bridge.
  • src/core/team-state-reducer.test.ts
    • Added new tests for the reduceTeamState function, covering various team lifecycle events and idempotency.
  • src/core/team-state-reducer.ts
    • Added a new file implementing the reduceTeamState function for managing team state based on correlated tool uses.
  • src/core/team-tool-correlation.test.ts
    • Added new tests for the TeamToolCorrelationBuffer to verify buffering, correlation, and flushing logic.
  • src/core/team-tool-correlation.ts
    • Added a new file implementing TeamToolCorrelationBuffer for buffering and correlating tool_use and tool_result blocks.
  • src/core/team-tool-recognizer.test.ts
    • Added new tests for the recognizeTeamToolUses function, covering various team tools and input validation.
  • src/core/team-tool-recognizer.ts
    • Added a new file implementing recognizeTeamToolUses to identify team-related tool uses from messages.
  • src/core/types/team-types.test.ts
    • Added new tests for team-related type guards (isTeamMember, isTeamTask, isTeamState).
    • Added new tests for structural correctness of TeamEvent types.
  • src/core/types/team-types.ts
    • Added new type definitions for TeamMember, TeamTask, TeamState, and various TeamEvent types.
    • Added corresponding type guards for team-related types.
  • src/core/types/unified-message.test.ts
    • Updated isUnifiedMessage tests to include new team message types.
  • src/core/types/unified-message.ts
    • Added new UnifiedMessageType values (team_message, team_task_update, team_state_change).
    • Added corresponding type guards for new team message types.
  • src/index.ts
    • Exported new team-related types, type guards, and interfaces.
  • src/types/events.ts
    • Added new team-related events to the BridgeEventMap interface.
  • src/types/session-state.ts
    • Added an optional team?: TeamState field to SessionState.
    • Marked the agents: string[] field as deprecated, now populated from team.members.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This is an excellent pull request that adds comprehensive support for observing agent teams. The changes are well-structured, following a clear implementation plan. The introduction of pure reducers, a correlation buffer, and new message types is well-thought-out. The code is accompanied by extensive and thorough tests, which is great to see. I found one critical issue regarding the implementation of idle member detection, which seems to be missing. Otherwise, the implementation is solid and aligns well with the detailed plan.

Comment on lines +1592 to +1598
if (prevMember.status !== member.status) {
if (member.status === "idle") {
this.emit("team:member:idle", { sessionId, member });
} else if (member.status === "shutdown") {
this.emit("team:member:shutdown", { sessionId, member });
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The logic to detect when a team member becomes idle appears to be missing. This if (member.status === "idle") block will likely never be reached because there is no code in team-state-reducer.ts that sets a member's status to idle.

The implementation plan (Phase 5.7, "Idle events") specifies that idle detection is a synthetic event based on task completion without a new task claim. This logic doesn't seem to be implemented here or in the state reducer. As a result, team:member:idle events will not be emitted, which is a gap in the feature as described.

To fix this, the logic for determining and setting the idle status on a TeamMember needs to be implemented, likely within the team-state-reducer.ts or as a more complex synthetic event generation step here in the session-bridge.ts as the plan suggests.

@teng-lin teng-lin merged commit db799e4 into main Feb 16, 2026
4 checks passed
@teng-lin teng-lin deleted the feature/agent-teams branch February 16, 2026 04:05
teng-lin added a commit that referenced this pull request Feb 24, 2026
Fix architecture principle violations #1, #3, #4, #7:

- Fix #1: Remove dual lifecycle mutation by deleting applyLifecycleFromBackendMessage()
  which was redundant with reduceLifecycle()

- Fix #3: Make transitionLifecycle() private. Add SESSION_CLOSING system signal and
  route coordinator's direct calls through process()

- Fix #7: Route ConsumerGateway's backend:relaunch_needed emission through the
  runtime as BACKEND_RELAUNCH_NEEDED system signal instead of emitting directly

- Fix #4: Route BackendConnector's inline broadcasts and event emissions through
  the runtime via routeSystemSignal callback:
  - Part A: Connect/disconnect lifecycle (cli_connected, backend:connected, etc.)
  - Part B: Slash passthrough results/errors (slash_command_result, slash_command_error)

This enforces the core design principle that all state mutations flow through
SessionRuntime.process(), which dispatches to the pure reducer and executes effects.
All 2902 tests pass, typecheck clean.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
teng-lin added a commit that referenced this pull request Feb 25, 2026
Update docs/architecture.md:
- Replace Tier 1 table with resolved summary (#1–4 all fixed)
- Update Tier 2 #6 (pendingInitialize now set in correct post-reducer hook)
- Update Tier 3 #14 (handleInboundCommand rejections fixed via SEND_TO_CONSUMER)
- Update Tier 3 #16 (trySendRawToBackend now runtime-internal only)

Also narrow SLASH_LOCAL_RESULT signal source type to "emulated" | "cli"
to match ConsumerMessage contract (caught by typecheck).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant