Skip to content

feat: Agent Teams improvements - SSE fix, team state parsing, and permission handling#298

Open
0x7551 wants to merge 1 commit intotiann:mainfrom
0x7551:feat/improve-agent-teams-v2
Open

feat: Agent Teams improvements - SSE fix, team state parsing, and permission handling#298
0x7551 wants to merge 1 commit intotiann:mainfrom
0x7551:feat/improve-agent-teams-v2

Conversation

@0x7551
Copy link
Contributor

@0x7551 0x7551 commented Mar 17, 2026

Summary

Rebased on latest upstream/main. Replaces #295.

Based on #258's Agent Teams feature, this PR fixes and enhances team collaboration stability and UX.

SSE Delay Fix (Hub)

  • Replace Hono's streamSSE (TransformStream/pull mode) with direct push-based ReadableStream, eliminating buffering delay under Bun

Team State Parsing Enhancement (Hub)

  • Improve <teammate-message> parsing: idle_notification, shutdown_response and other protocol messages
  • Extract effective team name from TeamCreate tool results
  • Parse Agent tool's runInBackground, isolation parameters
  • Normalize task ID agent:name@team suffixes
  • Add comprehensive test coverage (teams.test.ts)

Team Member Permission Handling (CLI + Hub)

  • Discovered core issue: teammate permission_request is part of Claude's internal team protocol, handled by team lead agent via SendMessage, not external RPC approval
  • Add --dangerously-skip-permissions for local mode to avoid terminal permission prompts blocking (HAPI has no interactive terminal)
  • Add deny rules for dangerous Bash commands (rm -rf, sudo rm, git push --force, etc.)
  • Remove ineffective teammate permission RPC approval logic and UI cards

Web UI Enhancement

  • Rewrite TeamPanel component: member cards show status, agent type, description, activity details
  • Natural TeamCreate tool card rendering
  • StatusBar adds team busy state detection
  • Mobile TeamPanel height limit to prevent overflow

Other Fixes

  • Clean up unused spawn outcome reporting code in Runner
  • Add resolveAgentRequestId to permission routes
  • Session cache and sync engine support team state operations

Test plan

  • Hub tests pass
  • Deployed and verified in production environment
  • Team session creation, member status updates, activity display working

Note: The AcpSdkBackend.test.ts failure in CI is a pre-existing timing race condition unrelated to this PR (also fails on clean upstream/main locally).

via HAPI

…mission handling

- Replace Hono streamSSE with push-based ReadableStream to fix Bun SSE buffering delay
- Enhance team state parsing: teammate messages, idle notifications, shutdown responses
- Extract effective team name from TeamCreate results, normalize task IDs
- Add --dangerously-skip-permissions for local teammate mode with deny rules for dangerous commands
- Rewrite TeamPanel component with expandable member activity details
- Add TeamCreate tool card rendering
- Add comprehensive team parsing tests
Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Review mode: initial
Findings: 1 Major, 1 Minor.
Testing: Not run (automation).

return { agentRequestId: teamPerm.requestId, teamPerm }
}
// Last resort: find by tool name match in agentState.requests
for (const [key, req] of Object.entries(requests ?? {})) {

Choose a reason for hiding this comment

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

[MAJOR] Tool-name fallback can approve/deny the wrong request if multiple pending requests share the same tool. The current loop returns the first match, which can misapply a decision to another request. hub/src/web/routes/permissions.ts:88
Suggested fix:

const matches = Object.entries(requests ?? {}).filter(
    ([, req]) => isObject(req) && req.tool === teamPerm.toolName
)
if (matches.length === 1) {
    return { agentRequestId: matches[0][0], teamPerm }
}


const handleApprove = async () => {
setLoading(true)
setActed('approve')

Choose a reason for hiding this comment

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

[MINOR] UI marks the permission as allowed/denied before the async action succeeds, so failures still show success. web/src/components/TeamPanel.tsx:135
Suggested fix:

const handleApprove = async () => {
    setLoading(true)
    try {
        await onApprove()
        setActed('approve')
    } finally {
        setLoading(false)
    }
}
const handleDeny = async () => {
    setLoading(true)
    try {
        await onDeny()
        setActed('deny')
    } finally {
        setLoading(false)
    }
}

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