ShellDenyGroups was defined in SystemPromptConfig but lacked full propagation
through parser, Loop fields, context injection, and system prompt population.
Per-agent overrides from other_config JSONB had zero runtime effect.
Changes:
- agent_store.go: Add ParseShellDenyGroups() to extract overrides from JSONB
- loop_types.go: Add shellDenyGroups field to Loop and LoopConfig, wire in NewLoop
- resolver.go: Wire agent-parsed shell deny groups into LoopConfig
- loop.go: Inject shellDenyGroups into context via store.WithShellDenyGroups
- loop_history.go: Populate ShellDenyGroups in system prompt config
- message_test.go: Fix macOS symlink path normalization in test expectations
Fixes test failures on macOS where /var/folders symlinks to /private/var/folders.
* feat: Implement MCP manager for server connections, tool registration, and deferred tool loading for agents.
* feat: Add tests for deferred tool activation logic within the tool registry and agent loop.
* fix(mcp): prevent deny list bypass via lazy activation + fix idempotency race
- Add PolicyEngine.IsDenied() to check deny patterns (incl. group: expansion)
before allowing lazily-activated deferred tools to execute
- Check IsDenied() in both single-tool and parallel execution paths in loop.go
- Make ActivateToolIfDeferred idempotent by checking activatedTools before
returning false, preventing concurrent goroutines from being blocked
- Add tests for deny-on-first-call, group deny patterns, and idempotent
concurrent activation
---------
Co-authored-by: viettranx <viettranx@gmail.com>
- Lead agents: auto-resolve team workspace as default (relative paths)
- Dispatched members: team workspace as default via req.TeamWorkspace
- Direct-chat members: own workspace default, team workspace accessible
- Add dataDir field to Loop/LoopConfig for global workspace root
- System prompt shows team workspace absolute path for model guidance
- Remove orphan task detector (superseded by post-turn dispatch)
- Log warning on OpenAI tool call argument parse failures
- Add card/list view toggle on teams page (matching agents page pattern)
- Card view: member chips with emoji/Bot icon, frontmatter, crown for lead
- List view: comma-separated member names with frontmatter tooltip on hover
- Show version badge from team settings in both views
- Enrich ListTeams API to bulk-fetch members with emoji from other_config
- Add agent emoji field (other_config.emoji) to create/update forms
- Show emoji in team members dialog instead of Bot icon when available
- Force restrict_to_workspace=true system-wide, remove UI toggle
- Add i18n keys for all 3 locales (en/vi/zh)
Major refactoring of the team system with multiple improvements:
## Removed legacy delegation tools
- Delete `delegate.go`, `delegate_async.go`, `delegate_sync.go`, `delegate_events.go`,
`delegate_policy.go`, `delegate_prep.go`, `delegate_state.go`, `delegate_search_tool.go`
- Delete `evaluate_loop_tool.go`, `handoff_tool.go`
- Remove all references and registrations from tool manager and policy
- Clean up TEAM_PLAYBOOK_IDEAS.md and TEAM_SYSTEM.md (moved to docs)
## Rename await_reply → ask_user
- Rename action `await_reply` → `ask_user`, `clear_followup` → `clear_ask_user`
- Rename functions `executeAwaitReply` → `executeAskUser`, `executeClearFollowup` → `executeClearAskUser`
- Update system prompt with stronger wording to prevent model misuse
- Model was confusing "await_reply" with general waiting; "ask_user" is unambiguous
## Fix auto-followup false positives
- Add `HasActiveMemberTasks(ctx, teamID, excludeAgentID)` store method
- Guard `autoSetFollowup()` in consumer: skip when lead has active member tasks
- Prevents auto-followup when lead is orchestrating teammates (not waiting for user)
## Task identifier zero-padding
- Change format from `T-1-xxxx` → `T-001-xxxx` (3-digit minimum)
## Refactor workspace WS handlers to filesystem-only
- Rewrite `teams.workspace.list/read/delete` to use pure filesystem (os.ReadDir/ReadFile/Remove)
- Remove DB dependency from workspace WS handlers
- Consistent with storage handler and workspace tools
- Simplify TeamWorkspaceFile type and frontend hook
## Add team events listing API
- New WS method `teams.events.list` with team_id, limit, offset params
- New HTTP endpoint `GET /v1/teams/{id}/events` with bearer auth
- New `ListTeamEvents(ctx, teamID, limit, offset)` store method
- JOIN with team_tasks for team-wide event filtering
## Extract team access policy
- New `team_access_policy.go` — centralized team tool access control
## Migration 000019: team_id columns
- Add team_id foreign key columns to relevant tables
## Other improvements
- Add team_id propagation through agent loop, tracing, sessions
- Update i18n locale files (en/vi/zh) for new tool labels
- Update frontend builtin-tools page and require-setup component
- Bump RequiredSchemaVersion for migration 000019
* feat(workspace): add team shared workspace for file collaboration
- Add workspace_write and workspace_read tools for agents to share files across team members
- Create team_workspaces DB table with migration 000017 (file metadata, pinning, tags)
- Implement PostgreSQL store layer for workspace CRUD operations
- Add RPC handlers for workspace list/read/delete from web UI
- Build React workspace tab with file listing, content preview, and delete
- Propagate workspace channel/chatID scope through delegation chain
- Auto-allow workspace tools in agent tool policy when agent belongs to a team
- Inject team workspace guidance into system prompt for team agents
- Add /reset command handler for clearing session history
- Harden MCP bridge context middleware to reject headers when no gateway token
- Add i18n strings for workspace UI in en/vi/zh locales
* feat(teams): add comprehensive task management with followup reminders and recovery
- Add task followup/reminder system with auto-set on lead agent reply and auto-clear when user responds on channel
- Add task recovery ticker to re-dispatch stale/pending tasks periodically
- Add task scopes, filtering by status/channel/chatID, and task events
- Add WS RPC handlers for task CRUD, assignments, comments, events, and bulk operations (teams_tasks.go)
- Add task detail dialog, settings UI for followup config, and scope filtering in web dashboard
- Add migrations 000018 (team_tasks_v2) and 000019 (task_followup)
- Extend team_tasks_tool with await_reply, clear_followup actions
- Auto-complete/fail team tasks when delegate agent finishes
- Add workspace file listing and team tool manager enhancements
* docs(teams): add team system architecture and playbook ideas documentation
- Add TEAM_SYSTEM.md with full architecture design covering task management, shared workspace, and delegation engine subsystems
- Add TEAM_PLAYBOOK_IDEAS.md outlining future team coordination layers (playbook, member capabilities, auto-learned patterns)
- Document data models, status flows, tool actions, followup reminder system, task ticker, execution locking, and workspace scope model
* fix(teams): resolve 6 critical bugs in team task system
- Fix unblock SQL: check array_length after array_remove (not before)
- Enforce single-team leadership in team creation
- Add requireLead() for approve/reject tool actions
- Validate cross-team dependency references in blocked_by
- Add team_id to handoff route for multi-team isolation
- Set blocked_by DEFAULT '{}' to prevent NULL array issues
* refactor(workspace): use stable userID as scope key instead of connection UUID
Workspace scope changed from (team_id, channel, chat_id) to (team_id, userID).
Fixes workspace fragmentation across WS tab refreshes and reconnections.
* feat(teams): add V1/V2 versioning with feature gating and optimized prompts
- IsTeamV2() helper gates advanced features (locking, followup, review, audit)
- V2 tool actions rejected for V1 teams with clear error message
- Ticker, gateway consumer, delegation hooks respect version flag
- TEAM.md renders v1/v2 sections conditionally
- Tool descriptions and params optimized (~38% token reduction)
- UI: version toggle in settings, V2 Beta badge, conditional rendering
- i18n: version modal keys for en/vi/zh
* fix(migration): use VARCHAR(255) for user ID columns and add metadata JSONB
- assignee_user_id, user_id, actor_id: TEXT → VARCHAR(255)
- Add metadata JSONB to team_task_comments and team_task_attachments
---------
Co-authored-by: Nam Nguyen Ngoc <namnn.0911@gmail.com>
Add workspace_sharing config in other_config JSONB to control per-user
workspace isolation. When enabled, users share the base workspace directory
instead of isolated subfolders — configurable separately for DMs and groups,
with a per-user allowlist override.
Backend: WorkspaceSharingConfig struct, ParseWorkspaceSharing(), conditional
isolation in loop.go/loop_history.go, 7 unit tests.
Frontend: prominent always-visible config section with contact search
combobox, sticky save bar layout fix, i18n (en/vi/zh).
Four per-agent settings stored in the database (and configurable via UI)
were silently ignored at runtime because the tool/system layer always
used the global config defaults instead.
**restrict_to_workspace**: Tools used the global config default baked at
startup. Fix: pass per-agent value through context; tools check context
override before falling back to constructor default.
**subagents_config**: ParseSubagentsConfig() existed but was never called.
All agents shared one SubagentManager with global limits. Fix: resolve
per-agent config in the agent resolver, store it on each spawned task,
and use it for limit checks, deny lists, and system prompt generation.
**memory_config**: Only the enabled toggle was read per-agent; search
weights (vector_weight, text_weight, max_results, min_score) were
hardcoded from PGMemoryStore defaults. Fix: extend MemorySearchOptions
with weight overrides, read per-agent config from context in the
memory_search tool.
**sandbox_config**: Only workspace_access was extracted per-agent; mode,
image, memory, CPU, timeout, network settings were discarded. Fix: pass
full sandbox.Config through context; Manager.Get() accepts an optional
config override for new containers.
Co-authored-by: Luvu182 <208665161+Luvu182@users.noreply.github.com>
- A1+C2: Include token usage in run.completed event payload for WS clients
- A2: Cost tracking with model pricing config, cost calculation, and cost summary API
- A3: Budget enforcement per agent with monthly budget limits (migration 000015)
- C1: External wake/trigger API (POST /v1/agents/{id}/wake) for orchestrators
- C3: Activity audit trail with structured logging and queryable API
- UI: Activity page, cost stat card on overview, budget section in agent detail
- i18n: Complete en/vi/zh translations for all new features
* refactor: remove managed/standalone mode distinction from codebase
Standalone mode is deprecated; managed mode is now the only mode.
Remove redundant "managed mode" qualifiers from comments, docs,
and error messages. Error strings now reference "database stores"
instead of "managed mode" for clarity.
* improve(onboard): streamline onboard process and env setup
Simplify onboard wizard, extract helpers to dedicated file,
update env example and entrypoint for default managed mode,
clean up prepare-env script, update i18n catalogs.
Self-Evolution: predefined agents can now optionally evolve their SOUL.md
(communication style/tone only) when self_evolve is enabled in other_config.
Identity, name, and operating instructions remain locked. Context propagation
flows through LoopConfig → Loop → context.WithValue → interceptor carve-out.
System prompt guides the agent on what it can/cannot evolve.
Instances Tab: new HTTP endpoints and UI tab for viewing/editing per-user
USER.md files on predefined agents. Includes owner-only access checks,
fileName validation (USER.md only), and cache invalidation.
UI: self-evolve toggle in General tab, create dialog, and setup wizard.
Agent type and evolve/static badges with tooltip explanations on cards
and detail header. TooltipProvider added to agents list and detail pages.
- Add persistent media storage (internal/media/) replacing temp file deletion
- Add MediaRef type for lightweight media references in session messages
- Refactor media pipeline to use bus.MediaFile{Path, MimeType} across all channels
- Add read_document builtin tool for PDF/DOCX/XLSX analysis via Gemini native API
- Move image sanitization from Telegram to shared agent/media layer
- Add media reload for multi-turn conversations (images from last 5 messages)
- Add reply-to-message media resolution for Telegram (re-download on reply)
- Add media inventory to compaction summary to preserve awareness after truncation
- Fix coreToolSummaries for read_image, read_document, create_image tools
- Add real-time trace update events via WebSocket broadcast
- Improve trace detail UI with media refs and tool result display
MCP tool search mode: when an agent has >30 MCP tools, tools are
deferred and a single mcp_tool_search meta-tool is registered instead.
Uses BM25 index for keyword search, activating matched tools on demand.
Shared connection pool: introduces Pool that maintains one physical
connection per MCP server name, shared across all agents via refcount.
Eliminates N×M duplicate connections (N agents × M servers).
- Revoke paired device now force-closes the active WebSocket connection
via pubsub (EventPairingRevoked → Server.DisconnectByPairing)
- Add group-level pairing policy ("pairing") to Discord, WhatsApp, and
Zalo Personal channels (matching existing Telegram/Feishu pattern)
- Block inactive agents at resolver level (chat, cron, delegation all
reject with "agent is inactive")
- Cascade: setting agent status to "inactive" auto-disables linked
channel instances via EventAgentStatusChanged pubsub
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Security: fix cross-agent MCP tool leak by cloning tool registry before MCP registration.
MCP: enforce mcp_ prefix on all tool names, add cache invalidation on server/grant changes,
add grant management endpoints, add group:mcp policy support for per-agent allowlisting.
Skills: persist full YAML frontmatter, auto-promote/demote visibility on grant/revoke,
simplify versioning, handle ZIP wrapper directories, expand tilde in skillsDir path.
Fixes: wrap DeleteSkill cascade in transaction, use atomic NOT EXISTS for revoke-demote,
create cancel context before storing server in map.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Root cause: TEAM.md instructed LLM to call team_tasks create + spawn
in the "SAME turn", but parallel tool execution caused LLM to
hallucinate task IDs. pendingTasksHint then leaked real task IDs
into error messages, causing cascade failures.
Changes:
- Auto-create team task when spawn is called without team_task_id
(subject from label param, fallback to task description)
- Remove pendingTasksHint() — stop leaking task IDs in error messages
- Update TEAM.md workflow to one-step delegation (just spawn)
- Orphan detection now queries DB for actual pending tasks
- Include team_task_id in spawn tool result for tracing
- Improve in-progress reminder wording
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
LLM models often hallucinate UUIDs when delegating, passing a wrong
team_task_id that doesn't exist. Previously the error was bare
("task not found") with no guidance, causing the model to get stuck.
Now the error includes a list of pending tasks so the model can
self-correct. Also refactored prepareDelegation to resolve team once
instead of 3 separate GetTeamForAgent calls, and extracted
pendingTasksHint() to deduplicate hint-building logic.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(store): expand tilde in skills storage directory path
The default skillsDir (~/.goclaw/skills-store) was not expanded,
causing os.MkdirAll to fail when creating skill upload directories.
* feat(skills): per-agent skill filtering with grant-based access control (#42)
Wire skill_agent_grants into the agent resolver so each agent only sees
skills explicitly granted to it. Add Skills tab to the web UI for
managing per-agent skill grants with toggle switches.
- Add SkillAccessStore interface to avoid import cycles
- Filter skills in resolver via ListAccessible + filesystem union
- Add GET /v1/agents/:id/skills endpoint with grant status
- Invoke onGrantChange callback to invalidate agent caches on grant/revoke
- Add agent-skills-tab React component with Switch toggles
- Allow read_file access to managed skills-store directory
- Fix rows.Err() propagation in ListAccessible/ListWithGrantStatus
Closes#42
- Fix resolvePath for nested non-existent dirs (use resolveThroughExistingAncestors)
- Channel-isolated workspace: user_agent_profiles.workspace stores channel prefix,
used as source of truth with backward compat for existing users
- Loop caches workspace per-user with CacheKindUserWorkspace invalidation via pubsub
- ContractHome/ExpandHome for portable ~-based paths in DB
- create_image saves to workspace/generated/YYYY-MM-DD/ instead of OS temp dir
- SOUL.md template: add ## Expertise section for domain knowledge
- Summoner buildEditPrompt: section guide, complete file output, frontmatter update
- Bus: Topic* constants for Subscribe/Broadcast keys, CacheKind* for payload kinds
- Teams, delegates, sessions, agent links: various enhancements
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Team delegation:
- Unify spawn/subagent/delegate into single spawn tool
- Sibling-aware announce suppression with artifact accumulation
- Fix auto-complete race (isLastDelegation guard)
- Add team tasks list limit (20) with search guidance
- Multi-round orchestration patterns in TEAM.md
- Communication guidance for initial vs follow-up delegations
Telegram resilience:
- Add retrySend wrapper (3 attempts, escalating delay) for network errors
- Fix HTML fallback: strip tags + unescape entities instead of showing raw HTML
- Pre-process HTML tags in LLM output to markdown before conversion pipeline
- Skip caption truncation entirely when > 1024 bytes, send text separately
- Auto-send large images (>5MB) as documents to avoid compression
Artifact forwarding:
- Fix missing ContentType on forwarded media (mimeFromExt for result.Media/ForwardMedia)
- Add deliver parameter to write_file for file attachment delivery
- Extend mimeFromExt with document MIME types
UI: fix regenerate dialog overflow, improve task list layout, delegation detail view
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement full thinking mode system: per-agent thinking_level config (off/low/medium/high)
stored in other_config JSONB, per-provider param injection (Anthropic budget_tokens, OpenAI
reasoning_effort, DashScope enable_thinking+thinking_budget), Anthropic extended thinking with
streaming parse and tool use block preservation via RawAssistantContent, thinking token tracking
in trace spans, and Web UI with agent config selector, chat thinking block rendering, and trace
thinking token display. No DB migration needed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add tool loop detection (toolloop.go): tracks repeated no-progress tool calls
using SHA256 hashing of args+results. Warning at 5 identical calls, force stop
at 10. Prevents Gemini models from burning tokens in infinite loops.
- Inject AVAILABILITY.md negative context when agent has no team/delegation
targets, so models don't waste iterations probing unavailable capabilities.
- Fix Dockerfile: create /app/.goclaw directory so Docker volume initializes
with correct goclaw:goclaw ownership instead of root:root.
- Update collapseToolCallsWithoutSig comments for clarity.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wire AgentToolPolicy from agent spec through loop creation and resolver, passing it to PolicyEngine.FilterTools for per-agent tool restrictions (nil = no restrictions). Set RestrictToWorkspace=true for default agent in managed mode seeding. Clean up thinking/placeholder messages in Discord and Telegram when agent suppresses empty/NO_REPLY responses by publishing empty outbound and deleting placeholders without sending messages.
Extend CronJob model with UserID field for multi-tenant isolation. Add agentID and userID filter parameters to ListJobs across all store implementations (file, pg). Support agent lookup by UUID in resolver for cron jobs that store agent_id as UUID. Change cron job handler signature to return CronJobResult struct with content, token usage (input/output tokens), and duration. Track execution metrics
Multi-agent AI gateway with WebSocket RPC, HTTP API, and messaging channel integrations.
Go port of OpenClaw with multi-tenant PostgreSQL, per-user isolation, security hardening,
and production observability.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>