Skip to content

feat(team): multi-bot Discord delivery, memory team scoping, vision fallbackFeat/team discord fixes#592

Open
kokorolx wants to merge 8 commits intonextlevelbuilder:mainfrom
kokorolx:feat/team-discord-fixes
Open

feat(team): multi-bot Discord delivery, memory team scoping, vision fallbackFeat/team discord fixes#592
kokorolx wants to merge 8 commits intonextlevelbuilder:mainfrom
kokorolx:feat/team-discord-fixes

Conversation

@kokorolx
Copy link
Copy Markdown

  1. fix(agent): Anthropic HTTP 400 — keep tool defs on final iteration
  2. feat(team): Direct delivery — members post via own bot
  3. feat(team): chat_team_map routing, memory team scoping, logging
  4. fix(tools): read_image fallback khi path outside workspace

@kokorolx kokorolx force-pushed the feat/team-discord-fixes branch from 28d70d0 to ad441fc Compare March 30, 2026 17:38
…TP 400

On the last iteration the loop set toolDefs = nil to force a text-only
response, but the conversation history still contained tool_use/tool_result
messages. Anthropic (and LiteLLM proxy) reject requests that include tool
messages without a top-level tools parameter.

Instead of stripping tools, keep them and set tool_choice="none" so the
API enforces text-only at the protocol level. Added ToolChoice field to
ChatRequest and wired it through both OpenAI-compat and Anthropic providers.

Also removed temperature from thinking-enabled requests to avoid proxy
400 errors (Anthropic requires temperature=1 default with extended thinking).
…rectly

When a team member (e.g. CTO) completes a task, their response is now
posted directly to the origin Discord channel via their own bot identity,
instead of being relayed through the lead agent (PM).

Changes:
- message tool: relax self-send guard for team task runs so members can
  use message() to post updates during execution
- consumer: post member completion result directly via member agent channel
  (resolved via ChannelForAgent), falling back to origin channel
- announce queue: when all entries are direct-delivered, instruct leader
  to respond NO_REPLY unless it has new information to add
- manager: add ChannelForAgent() to resolve agent key → channel name

This creates a natural conversation flow where each agent speaks for
themselves, like a normal team chat.
…ry logging, agent workspace preservation

- Add chat_team_map support for Discord channels to route inbound messages
  to correct team based on channel snowflake ID
- Scope memory search (FTS + vector) by team_id to prevent cross-project
  contamination when same PM agent serves multiple teams
- Populate team_id on memory_documents and memory_chunks during write
- Relax NO_REPLY instruction to allow PM to create follow-up tasks
  (e.g. CTO review gate) after direct delivery of member results
- Add direct delivery logging with channel, chat_id, fallback info
- Fix Discord connect race: register message handler after bot identity fetch
- Preserve agent base workspace in team context for file tool access
- Add TryMarkListed atomic helper for team task state transitions
…nied

When team workspace is active, uploaded images are in per-user .uploads/
dir which falls outside the team workspace boundary. Instead of failing
with access denied, fall back to context images already loaded in memory
by enrichInputMedia.
@kokorolx kokorolx force-pushed the feat/team-discord-fixes branch from ad441fc to efb8b5f Compare March 31, 2026 02:00
kokorolx added 4 commits April 2, 2026 00:56
…ults on budget exceed

- Parallel tool batch: collect deferredWarnings, append all tool_result messages
  first, then warnings — prevents user-role messages from interleaving with
  tool_result blocks (Anthropic requires tool_results immediately after tool_use)
- When toolResultBreak fires mid-batch, finish appending remaining tool_result
  messages before breaking to keep assistant/tool_result pairs intact
- On tool budget exceeded: synthesize tool_result for each pending tool_use
  before injecting the budget-exceeded user message

- gateway_announce_queue: strengthen follow-up task prompt (MUST check, not SHOULD)
- gateway_consumer_handlers/normal: send LLM error alerts on agent run failure
- shell_deny_groups: fix 'host' deny pattern — match only at command position
  to avoid blocking 'hostname', 'hostnamectl' etc
- claude_cli_deny_patterns: same host pattern fix
Tasks assigned an owner but never dispatched (e.g. PM session timeout mid-turn)
accumulate as pending with owner_agent_id set. Without this fix they sit until
2h stale threshold — or forever if PM doesn't retry.

- Add TaskDispatcher interface (DispatchTaskToAgent + CachedGetAgentByID + Store)
- Add SetDispatcher() on TaskTicker; wire TeamToolManager at startup via type assertion
- Add Step 6 in recoverAll: ListOrphanedPendingTasks (pending + owner + updated_at > 10m)
  → dispatch directly to assigned agent, bypassing PM
- Add ListOrphanedPendingTasks to TaskRecoveryStore interface + PG + SQLite impls
- Guard GetTeam nil result to prevent nil pointer dereference
- Use WithCrossTenant context so GetTeam bypasses tenant filter
- Remove tenant_id WHERE clause from ListOrphanedPendingTasks (cross-tenant query)
Prevents 'can't find browser binary' on systems where Chrome/Chromium
is installed in non-standard paths (e.g. /snap/bin/chromium)
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