nexus-ai:基于多智能体协作的数字员工平台项目

OpenClaw for Teams

分支1Tags0
文件最后提交记录最后更新时间
refactor agent detail page shell 17 天前
Add Workspace preview and revision support Co-authored-by: Codex <noreply@openai.com> 1 个月前
Improve agent workspace and chat UX 27 天前
Fix Google Workspace SSO provider routing and org member links (#582) * Fix Google Workspace SSO provider routing * Fix invalid org member platform links * fix bug * fix bug11 天前
Fix Google Workspace SSO provider routing and org member links (#582) * Fix Google Workspace SSO provider routing * Fix invalid org member platform links * fix bug * fix bug11 天前
release: update version to v1.9.3 21 天前
feat: add Exa AI-powered search tool Add Exa (exa.ai) as a search provider in two ways: - Standalone exa_search tool with full feature support (category filtering, domain filtering, content modes: text/highlights/summary) - New engine option in the existing web_search tool for simple use Files changed: - backend/app/services/tool_seeder.py: Exa search tool definition + web_search engine option - backend/app/services/agent_tools.py: _search_exa (simple) and _exa_search (full) functions - backend/app/config.py: EXA_API_KEY setting - .env.example: EXA_API_KEY documentation 1 个月前
fix: use bash in entrypoint.sh to prevent CRLF/set-option crash on Linux; add .gitattributes for LF enforcement 2 个月前
Fix Google Workspace SSO provider routing and org member links (#582) * Fix Google Workspace SSO provider routing * Fix invalid org member platform links * fix bug * fix bug11 天前
Improve agent workspace and chat UX 27 天前
fix: allow chat model override for collaborators 21 天前
release: OKR系统、Workspace面板、多渠道支持及多项修复 (#479) * fix(chat): restore scroll by fixing main-content height for chat page Root cause: .main-content uses min-height: 100vh (grows with content), so .chat-messages overflow-y: auto never triggers. Fix: - Add .main-content.chat-page with height: 100vh + overflow: hidden - Detect chat route in Layout.tsx (useMatch) to apply the modifier - Chat root div now fills 100% height (flex column) - Restore padding via scoped CSS rules for page-header and chat-container * fix(chat): add minHeight:0 to chat flex wrapper to enable scroll Root cause: the live WebSocket chat wrapper div had flex:1 but no minHeight:0. In CSS flexbox, without minHeight:0 a child can grow to its content height (1373px) ignoring the parent's constrained flex boundary (457px = 100vh - 206px). This prevented overflow-y:auto on the inner chatContainerRef from ever triggering a scroll. Fix: add minHeight:0 and overflow:hidden to the wrapper div so the flex chain correctly constrains the scrollable message area. * fix(chat): parse [image_data:] markers in ChatMessageItem + remove deprecated /chat route Changes: 1. AgentDetail ChatMessageItem: strip [image_data:data:url] markers from displayed text, extract image data URLs, and render them as thumbnails. Applies to both live WebSocket messages and history loaded from DB. 2. App.tsx: remove deprecated 'agents/:id/chat' route and Chat import. The chat interface lives in AgentDetail as a tab (#chat), not as a standalone route. Keeping this route caused repeated confusion where fixes were applied to the wrong component. * fix(chat): deduplicate image display - strip markers always but only render thumbnail when imageUrl absent * ui: move A2A async toggle to bottom of Company Info tab, before Danger Zone * fix: hide msg_type param from LLM when a2a_async is disabled When a2a_async_enabled is False, the send_message_to_agent tool schema is dynamically simplified to remove the msg_type parameter. This prevents the LLM from selecting notify/task_delegate modes (which get silently overridden to consult) and confusing users who see the raw tool call arguments in the chat UI. * fix: show agent-to-agent sessions in Other Users tab Agent-to-agent sessions store creator's user_id, causing them to be filtered out from the Other Users admin view. Exempt source_channel=agent sessions from the user_id filter so they always appear. * feat: add DingTalk media message support (image, file, voice, video) - Add dingtalk_token.py: global access_token cache with auto-refresh - Add dingtalk_reaction.py: thinking indicator (reaction) during LLM processing - Enhance dingtalk_stream.py: media download pipeline, auto-reconnect with exponential backoff, support for picture/richText/audio/video/file messages - Update dingtalk.py: accept image_base64_list and saved_file_paths in message processing, forward media to LLM with vision support - Update dingtalk_service.py: add download_dingtalk_media convenience wrapper Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: mirror A2A replies to shared chat session for visibility When an agent sends a notify/task_delegate message, the target agent's reply was only saved to its Reflection Session (source_channel=trigger), not to the shared A2A chat session. This made A2A conversations invisible in the admin 'Other Users' chat history. Now the reply is also saved to the A2A session via _a2a_session_id passed through _wake_agent_async → wake_agent_with_context → dummy trigger config → _invoke_agent_for_triggers. * fix: remove hardcoded 2-round tool limit for A2A wake The 2-round max_tool_rounds_override was too restrictive for A2A wake invocations, causing agents to hit the limit before completing basic tasks. Each agent already has a configurable max_tool_rounds setting (default 50), which provides sufficient protection against runaway tool calls. * fix: load latest 500 messages instead of oldest 500 For sessions with thousands of messages, the messages API was returning the oldest 500 (ORDER BY created_at ASC LIMIT 500), making recent A2A conversations invisible. Now uses a subquery to fetch the latest 500 messages by created_at DESC, then displays them in chronological order. * stop tracking .agents files * perf: fix N+1 queries in session list API scope=all was issuing 1+2N DB queries (1 count + 2 agent-name lookups per session). scope=mine was issuing 2N queries (1 user-count + 1 total per session). Both are now replaced with 3-4 bulk queries total, regardless of session count. Affected endpoint: GET /api/agents/{id}/sessions?scope=all|mine * chore: add deploy.md to .gitignore (contains private server credentials) * fix: enable fallback model when primary LLM returns error - Backend: call_llm returns error strings rather than raising exceptions; detect error-prefixed responses and raise RuntimeError to trigger the existing fallback model retry logic in the websocket handler - Frontend: handle 'info' WebSocket message type; show a subtle auto-dismissing info banner (6s) when the system switches to fallback model, with a manual dismiss button * fix(okr): auto-create OKR Agent per tenant when OKR is first enabled Previously, seed_okr_agent() was a global startup-time seeder with a file marker — new tenants enabling OKR via Company Settings never got an OKR Agent, causing 'OKR Agent not found' errors in the UI. Fix: - Add seed_okr_agent_for_tenant(tenant_id, creator_id) in agent_seeder.py: tenant-scoped, on-demand seeder with DB-only idempotency (no file marker), safe to call multiple times. - In update_okr_settings (PUT /api/okr/settings): detect False->True transition on 'enabled' and fire seed_okr_agent_for_tenant as a background asyncio task so the API response is not blocked. * fix: reload model config per-message for real-time Settings updates Previously the LLM model was loaded once at WebSocket connect time and cached for the entire session. Changing the model in Settings required a page refresh to take effect. Now the agent's primary/fallback model is re-fetched from the DB on every incoming message, so configuration changes apply to the next message immediately. * fix(okr-ui): delay re-fetch after OKR enable + fix toggle flexShrink - After enabling OKR, the backend creates the OKR Agent asynchronously. The frontend now waits 2.5s then invalidates the members-without-okr query so the 'Open OKR Agent Chat' button appears automatically without requiring a manual page refresh. - While the agent is being seeded, shows a spinner 'Creating OKR Agent...' instead of the misleading 'OKR Agent not found' text. - Toggle label now has flexShrink:0 to prevent layout overflow. * fix(okr-ui): fix React import for TS build (add explicit React import) * fix(okr-ui): force refetch OKR settings on mount to fix stale cache after company switch The OKR page was using ['okr-settings'] as query key (no tenantId), so React Query served a stale cached response when switching companies. If the previous company had OKR disabled, the new company's OKR page would still show 'OKR is not enabled' until the cache expired. Fix: add user.id to queryKey so entries are per-user, and set staleTime:0 + refetchOnMount:true so navigation to the OKR page always fetches fresh settings data. * fix(okr-ui): replace label toggle with button; invalidate agents on OKR enable - OKR toggle: replace label/checkbox with <button> element (consistent with the rest of the codebase). Eliminates the label implicit-width side-effects that made the toggle area appear too wide. - seeding timeout: also invalidates ['agents'] query so the sidebar Agent list updates automatically (OKR Agent appears without manual page refresh). Increased timeout to 3000ms for safer backend creation timing. * fix(okr): remove is_system filter from OKR Agent lookup queries The is_system column may be NULL for agents created on-demand via seed_okr_agent_for_tenant() (new tenants enabling OKR via settings). Filtering by is_system==True silently returned no results, causing 'OKR Agent not found' to appear in the UI even though the Agent actually existed in the sidebar. Fix: query by tenant_id + name.ilike('%OKR%') which is unambiguous within a tenant. Applied to both members-without-okr and trigger-member-outreach endpoints. * fix(okr-ui): resize OKR toggle switch to 36x20px The previous OKR toggle switch was sized 40x24px, making it noticeably larger than the other standard toggle switches in the Enterprise Settings (e.g., LLM tools, which are 36x20px), leading to a 'wrong width' visual anomaly. Fix: resize the OKR toggle container to 36x20px and its inner circle to 16x16px to match the platform's standard toggle dimensions. * fix(okr-ui): fix field name mismatches in MembersWithoutOKRPanel The panel was silently not rendering because: 1. Frontend used 'members' but backend returns 'members_without_okr' 2. Frontend used 'member.name' but backend returns 'display_name' When data.members was undefined, data.members.length threw TypeError, causing React to silently remove the component from the render tree. Fix: update TypeScript interface and component to use the correct field names that match the API response. * fix(okr-ui): fix field name mismatches in MembersWithoutOKRPanel The panel was silently not rendering because: 1. Frontend used 'members' but backend returns 'members_without_okr' 2. Frontend used 'member.name' but backend returns 'display_name' When data.members was undefined, data.members.length threw TypeError, causing React to silently remove the component from the render tree. Fix: update TypeScript interface and component to use the correct field names that match the API response. * fix(okr-api): fix members-without-okr endpoint and add owner_display_name Three backend fixes: 1. Fix User query in members-without-okr: replace User.full_name/User.email (which don't exist as plain DB columns; email is an association proxy that throws NotImplementedError when used in select()) with User.display_name. The endpoint has been 500-crashing silently, so the panel never rendered. 2. Add owner_display_name to ObjectiveOut schema. 3. Add bulk lookup of owner display names in list_objectives: after fetching objectives, query User.display_name and Agent.name for member-level objectives and pass them through to the response, so member OKR cards correctly show who the objective belongs to. Also add top-level imports for User and Agent in okr.py to support the new owner name lookup code in list_objectives. * fix(okr-api): add backward-compat members alias to prevent TypeError on old frontends When the backend was updated (members_without_okr field) without a simultaneous frontend rebuild, old frontend builds calling data.members.length crashed with TypeError: Cannot read properties of undefined (reading 'length'). Adding 'members' as an alias alongside 'members_without_okr' keeps old frontend builds working while new builds are deployed. * feat(okr): fix agent link URL + add auto-sync relationship network Two fixes + one new feature: 1. Fix 'Chat with OKR Agent' button: navigate to /agents/{id} (agent detail page) instead of /chat/{id} (which was incorrect). 2. Auto-sync OKR Agent relationships on enable: - When OKR is toggled on, after seeding the agent, automatically connect it to ALL active OrgMembers (org-structure-synced humans, e.g. Feishu) as team_member relationships and ALL company-visible agents as collaborator relationships. - Regenerates the workspace relationships.md so the context is immediately available to the OKR Agent. 3. Add POST /api/okr/sync-relationships endpoint + matching 'Sync Now' button in Company Settings → OKR tab so admins can re-sync at any time without having to disable and re-enable OKR. * feat: hash-based tab links, fix agent chat URL, fix sync auth, add tenant delete Changes: 1. EnterpriseSettings.tsx — Hash-based tab deep-linking: /enterprise#okr, #models, #tools, #skills, #invites, #quotas, #users, #org-structure, #approvals, #audit. URL updates on tab switch via replaceState. 2. OKR Agent button — href now includes #chat so users land directly on the chat tab of the agent page. 3. Sync Now button — switched from raw fetch() to project-standard fetchJson() so the Authorization header is correctly included (was returning 401). 4. OKR.tsx — 'Enable OKR in Company Settings' button now navigates to /enterprise#okr (was using ?tab=okr query param which had no effect). 5. tenants.py — Added DELETE /tenants/{id} endpoint (was returning 405 Method Not Allowed). Performs ordered cascade deletion: relationships → tasks → sessions → triggers → channel_configs → agent_permissions/credentials → agents → OKR/org data → users → tenant. Returns fallback_tenant_id pointing to another company the caller belongs to. * fix: tenant delete table names, remove OKR auto-connect mode, remove auto-sync 1. tenants.py — Fix DELETE /tenants/{id} cascade table names: - chat_messages (was: messages) - agent_triggers (was: triggers) - approval_requests with agent_id subquery (was: 'approvals WHERE tenant_id') - Move approval_requests + notifications deletions BEFORE agent deletion to avoid FK constraint violations. 2. okr.py — Remove auto-sync of relationships on OKR enable. The OKR Agent's relationship list is now managed solely by admins: manually (via the Relationships tab) or via POST /api/okr/sync-relationships. 3. AgentDetail.tsx — Remove isSystem/Auto-Connect Mode guard from RelationshipEditor so OKR Agent's Relationships tab works identically to every other agent's — fully editable, supporting add/edit/delete. * feat: OKR relationship-based member filtering + platform user sync * fix: chat_messages delete uses agent_id not session_id chat_messages table has no session_id column. Delete directly via: DELETE FROM chat_messages WHERE agent_id IN (...) chat_sessions also deletes via agent_id (already correct). * feat(okr): implement Nudge Members via run_agent_oneshot - heartbeat.py: add run_agent_oneshot(agent_id, prompt, max_rounds) - okr.py: rewrite trigger_member_outreach with real member query + chat history injection * feat(okr): implement Nudge Members via run_agent_oneshot * fix(okr): restore Sync Now + Nudge Members buttons lost in branch merge Backend: - Add _sync_okr_agent_relationships() helper + sync-relationships endpoint - Fix members_without_okr: relationship-filtered, returns tracked_user_ids/agent_ids - Lenient OKR Agent lookup (no is_system=True requirement) Frontend (OKR.tsx): Restore MembersWithoutOKRPanel with Nudge Members button Frontend (EnterpriseSettings.tsx): Add Sync Relationship Network + Sync Now button * fix(okr): restore Sync Now + Nudge Members buttons lost in branch merge * fix(okr): fix ImportError AgentRelationship location + settings returns okr_agent_id - AgentRelationship/AgentAgentRelationship are in app.models.org (not .agent) → was causing 500 on members-without-okr and sync-relationships - Add okr_agent_id to OKRSettingsOut + get_okr_settings query → UI gets OKR Agent ID from reliable /settings endpoint - members_without_okr: fallback to all members when relationship list empty - EnterpriseSettings: use settings.okr_agent_id as primary source - Fix button URL: /agents/{id} instead of /chat/{id} * fix(okr): fix ImportError AgentRelationship location + settings returns okr_agent_id * fix(okr): fix AgentAgentRelationship import in trigger_member_outreach (models.org not models.agent) * fix(okr): fix AgentAgentRelationship import in trigger_member_outreach * fix(okr): fix User field names in trigger_member_outreach (full_name/email, not username/display_name) * fix(okr): fix User field names in trigger_member_outreach * fix(okr): fix all User field refs — use display_name/avatar_url (not full_name/email/username) * fix(okr): fix all User field refs — display_name not full_name * fix: correct Feishu free busy scope * fix: scope agent relationship candidates by tenant * fix(okr): enforce send_message_to_agent for agents; fire-and-forget to stop infinite loop; reduce max_rounds * fix(okr): correct agent tool + stop infinite loop * fix: OKR UI and notification improvements - Move Nudge Members button to top of member list header (always visible) - Fix notification title: send_message_to_agent and send_file_to_agent now use their own action_type instead of being aliased to send_feishu_message - Add owner_name to ObjectiveOut: batch-resolve User/Agent names so member objectives show real names (e.g. 'PI', 'PM') instead of raw 'agent' label - Update OKR.tsx Objective type and memberGroups to use owner_name * build: update dist.zip with OKR UI and notification fixes * fix(okr): improve outreach \u2014 channel priority, agent OKR recording, correct max_rounds - channel_hint: prioritize any external channel over web notification so Feishu/DingTalk/WeChat Work members receive messages in their daily tool - agent member block: include agent UUID so OKR Agent can pass correct owner_id when calling create_objective after A2A reply - task prompt: add Step 3/4 for agents \u2014 parse reply, call create_objective + create_key_result(s) to record OKR immediately after A2A exchange - remove contradictory FIRE-AND-FORGET section (only humans are F&F now) - max_rounds: bumped from N*2+3 to N*5+3 to accommodate OKR write calls * fix(okr): normalize UUID to str in owner_name resolution to fix type mismatch * fix(okr): embed real UUID in agent prompts; add OrgMember lookup for Feishu users * fix(okr): friendly fallback label for unresolvable owners; validate owner_id in create_objective - OKR.tsx: replace UUID prefix fallback with '用户'/'数字员工' for OKRs whose owner_id cannot be resolved (phantom/unlinked UUIDs) - agent_tools._create_objective: validate owner_id against User/OrgMember/Agent tables before accepting it, preventing hallucinated UUIDs from being stored * fix(okr): add owner_name resolution in create_objective tool - When owner_id is not provided or fails UUID validation, fall back to resolving the owner by display_name / OrgMember.name. - Allows OKR Agent to record OKRs for Feishu channel users by passing owner_name='王珂' instead of an invented UUID. - Resolution priority: User.display_name → OrgMember.name (for users), Agent.name (for agents). * feat(okr): inject company OKR context into outreach prompt; fix agent UUID template; adaptive max_rounds - Fetch current-period company OKRs before building the prompt and include them under '公司目标' so members can align their individual OKRs - Restore agent member block with verbatim STEP 1-4 UUID-embedded create_objective template (prevents LLM from hallucinating nil UUID) - max_rounds now adaptive: humans × 2 + agents × 6 + 3 buffer - Clarify TOOL RULES: agents = STEP 1-4 collect+record; humans = fire-and-forget * feat(okr): inject company OKR context into outreach prompt; fix agent UUID template; adaptive max_rounds * fix(okr): expose owner_name to create_objective JSON schema - The LLM was rejecting Feishu users because it was trying to pass phantom UUIDs or complaining about inactive accounts, as it didn't know owner_name was a valid param. - Added owner_name to the tool JSON schema so the LLM is aware it can use names directly. * feat(okr-ui): add distinct agent badge in OKR board - Render agent objectives with a purple icon and styling to distinguish digital employees from human members in the dashboard * fix(frontend): import React to resolve TS compilation error in EnterpriseSettings * fix(okr): add owner_name resolution to create_objective * fix(okr-ui): prevent objective owner badge from wrapping on long titles * fix(feishu): use stable user_id over open_id for user resolution to prevent org-sync duplicates * style(okr): merge owner badge into inline text flow * fix(okr-ui): add missing closing div for layout fix * style(okr): align expand chevron to top of title text * style(okr): move nudge button and description below Members Without OKR title * fix(channel-user): deduplicate users by username prefix before creating new account * feat(okr): sync O+KR context to nudge prompt; update UI to redirect to OKR Agent chat history * debug(feishu): log user_id_from_event alongside open_id for sender ID verification * fix(channel-user): use prioritized limit(1) query in _find_org_member to prevent MultipleResultsFound crash * fix(okr): exclude NULL user_id OrgMembers from members-without-okr so linked users with OKRs are correctly recognized as covered * fix(system-agents): block deletion of is_system agents; harden seeder dedup to auto-stop extra OKR Agents on startup * docs: rename Pulse engine references to Aware * feat(okr): add okr_agent_id to OKRSettings and create DB unique constraint for system agents * fix(migration): shorten revision ID to fit varchar(32) limit * fix(okr): resolve OrgMember.id → user_id in create_objective; fix bad owner_id in DB * fix(okr): show genuine new Feishu-only members in No OKR list * refactor(okr): replace two-pass member query with generic canonicalization * fix(okr): improve owner tag UX; staleTime=0 so data always fresh on navigation * Fix Feishu channel user identifier handling * Improve migration safety and performance for chat messages - Add idempotency to 'increase_api_key_length' migration - Add database index to ChatMessage.conversation_id - Clean up imports in WeCom API and ChannelUserService * Refine channel user lookup and UI indentation in AgentDetail - Optimize DingTalk/Feishu lookup logic in channel_user_service.py - Fix code indentation and formatting in AgentDetail.tsx * Restore AgentDetail.tsx to main branch version * fix: harden channel identity resolution * 不使用openid进行查询 * user_id 可以缺失 * fix:import error * fix(migration): merge okr_agent_id and increase_api_key_length heads * Add Workspace preview and revision support Co-authored-by: Codex <noreply@openai.com> * Add Workspace preview and revision support * Fix Workspace operation panel layout * Refine Workspace file references and PDF preview * Move Workspace file tree to right side * Refine Workspace right sidebar collapse * fix: heartbeat run_agent_oneshot uses new app.services.llm import path PR #411 restructured llm_utils.py → llm/__init__.py but the run_agent_oneshot function in heartbeat.py still referenced the old module, causing ModuleNotFoundError and silently dropping all OKR member outreach messages. * Collapse chat navigation when opening Workspace panel * Move Workspace tree toggle into document area * Simplify Workspace file tree chrome * Use public base URL for published pages * Make Workspace autosave feedback visible * Refine Workspace tree and download controls * Improve Workspace tree toggle visibility * [codex] Add Workspace operation panel (#419) * Add Workspace preview and revision support * Fix Workspace operation panel layout * Refine Workspace file references and PDF preview * Move Workspace file tree to right side * Refine Workspace right sidebar collapse * Collapse chat navigation when opening Workspace panel * Move Workspace tree toggle into document area * Simplify Workspace file tree chrome * Use public base URL for published pages * Make Workspace autosave feedback visible * Refine Workspace tree and download controls * Improve Workspace tree toggle visibility * fix(migration): merge workspace_revisions and merge_okr_api_key heads * fix(websocket): emit workspace_activity in tool_call events for file tools PR #419 added WorkspaceOperationPanel in the frontend with auto-open logic triggered by workspace_draft / workspace_activity WebSocket events. However, the backend never emitted these events — the panel could not auto-open. Adds workspace_activity: {action, path, tool, ok} to tool_call events when status=done for write_file, edit_file, delete_file and convert_* tools. This mirrors the existing live_preview pattern used by AgentBay. * feat(tools): add built-in format conversion tools (Word/Excel/PPT/PDF) - Added convert_csv_to_xlsx, convert_html_to_pptx, convert_markdown_to_docx and two pdf conversion tools - Updated tool_seeder to register the tools - Added WeasyPrint OS dependencies to backend Dockerfile - Appended parsing dependencies (weasyprint, markdown, beautifulsoup4) to pyproject.toml * fix(Dockerfile): correct package libgdk-pixbuf-2.0-0 * fix(backend): add chinese fonts to Dockerfile for weasyprint * feat(ui): add delete button to workspace files on hover * fix(okr): handle channel-only members (no User account) correctly in covered_ids check - members_without_okr: channel-only members with OrgMember.id as owner_id were never excluded from the 'without OKR' list because the covered_ids check was skipped entirely for user_id=None rows. Now checks row.id (OrgMember.id) in covered_ids as well. - create_objective: when owner_type=user and owner_id matches an OrgMember that has no linked user_id (channel-only), previously returned HTTP 422. Now stores OrgMember.id directly as owner_id so the OKR Agent can create OKRs for channel members and have them properly excluded from the 'members without OKR' panel. * fix(okr): resolve OrgMember.id → User.id in _create_objective agent tool When OKR Agent calls create_objective with an OrgMember.id as owner_id for a user-type objective, stored OrgMember.id directly causing '?' display. Now resolves OrgMember.id → linked User.id when available. * fix(okr): handle OrgMember.id as owner_id in name resolution and covered_ids check Two defensive fixes for when OKR Agent stores OrgMember.id as owner_id instead of the linked User.id: 1. list_objectives: after User.id name lookup fails, fall back to querying org_members table by id to get display name. Prevents '?' from showing. 2. members_without_okr: for linked members (user_id != NULL), check BOTH user_id and OrgMember.id against covered_ids. Previously only checked user_id, so a member with owner_id=OrgMember.id in their OKR would still appear in the 'without OKR' list even though an OKR existed. * fix(feishu-ws): add reconnection loop to prevent 4h+ silent message loss Previously, if _connect() exited (server close or exception), the async task entered an infinite sleep(3600) loop — keeping the task 'alive' but with a permanently dead WS connection. No reconnect, no error log, all messages silently dropped. Now _run_async_client() retries _connect() in a loop: - Normal exit (_connect() returns): reconnect after 5s - Exception: log error and reconnect after 10s - CancelledError: clean disconnect and exit Also removes the defunct ping_task creation which was only called after _connect() exited (i.e., too late to be useful). * fix(feishu-ws): use health-watch loop instead of aggressive 5s reconnect spam _connect() is non-blocking — it establishes the WS and immediately starts _receive_message_loop() as a task. The SDK itself handles reconnects (infinite retries, 120s interval via _reconnect_count=-1). Previous fix (5s reconnect loop) caused constant false 'Connection closed' warnings because _connect() returns quickly after connecting. New approach: 1. Call _connect() once (starts SDK's receive loop) 2. Start ping loop 3. Health-watch every 60s: if client._conn is None for >3min (SDK stuck), force a hard reconnect as last resort * feat(okr-ui): hash-based tab routing, wider toggle, #Chat nav - EnterpriseSettings: each tab now has its own hash address (e.g. /enterprise#okr). Tab click updates window.location.hash; hashchange event keeps state in sync for back/forward navigation. - OKR page 'Enable OKR' button: navigate to /enterprise#okr instead of /enterprise?tab=okr. - OKR toggle: widen from 40×24 to 52×28 px for a more comfortable click target; knob adjusted to 24×24 px. - 'Chat with OKR Agent' button: href now includes #Chat suffix so the agent detail page opens directly in chat mode. * fix(okr): auto-create OKR Agent on enable, fix #chat hash 1. update_okr_settings: when enabled=True and no okr_agent_id exists, auto-call seed_okr_agent_for_tenant() so the OKR Agent is created immediately for the current tenant. 2. seed_okr_agent_for_tenant: was missing the critical step of writing okr_agent_id back to OKRSettings — added it. 3. Chat link: #Chat → #chat (lowercase to match agent detail routing). * fix(okr): rewrite period generation — fix duplicate Q4 and missing Q1 The old list_periods logic had multiple bugs: - _prev_start had broken cross-year quarter math ((month-4)%12 wrong) - Inner loop called _compute_current_period which always returns TODAY's period regardless of the loop variable s - pe was often None, falling through to wrong fallback calculation - Result: Q4 2025 appeared twice, Q1 2026 was missing New approach: step from a known anchor point (2 periods before current) and generate exactly 4 consecutive periods [prev2, prev1, current, next1] using simple, correct arithmetic for quarterly/monthly/custom modes. * fix(okr): lock cadence and expand period history * fix(okr): clarify cadence lock and dropdown behavior * fix(okr): improve cadence setup and report triggers * fix(okr): clarify report triggers and tabs * fix(okr): stabilize report tab header * feat(okr): skip daily reports on non-workdays * feat(okr): redesign daily reporting flow * feat(okr): add member daily report tool * feat(okr): restrict daily collection to relationships * fix(okr): stabilize daily collection replies * fix(okr): route collection through channel and async a2a * fix(okr): send agent collections via deterministic a2a * chore: replace expired QR code with new Clawith_QRcode.png Updated all 5 README files (EN, ZH, JA, KO, ES) to reference the new community QR code image. Deleted the old QR_Code.png. * chore: add new community QR code image * fix(okr): simplify daily collection flow * fix(ui): simplify company info layout * fix(okr): stabilize report capture and clean ui * refactor(okr): unify daily report reply flow * fix(feishu-ws): stop creating duplicate connections that cause 'kicked by new connection' Root cause: the health-watch loop was calling _connect() + _ping_loop() on every reconnect attempt, creating additional WS connections and ping tasks alongside the SDK's own internal ones. Feishu's server detected multiple connections from the same App ID and kicked one every ~5 min, causing a cycle of connect → kick → reconnect → kick. Fix: only call _connect() + _ping_loop() once during initial startup. Let the SDK's built-in auto_reconnect handle all subsequent reconnections. The health-watch now only logs connection status changes for diagnostics. * fix(okr): patch all tenant okr agents * fix(okr): improve report browsing * fix(ui): refine okr report browsing * fix(tenant): backfill org members on tenant join flows * feat(chat): add primary platform sessions and unread badges * docs(test): translate primary session cases to chinese * chore(docs): move local test cases out of repo root * fix(chat): label primary sessions in list * fix(relationships): label platform org members * fix(relationships): show platform user badge * fix(okr): self-heal missing daily report tool rows * fix(triggers): route trigger replies to owned sessions * feat: add WeChat, WhatsApp, and Google Workspace channel support - Add WeChat channel API and service with QR code login flow - Add WhatsApp channel API integration - Add Google Workspace OAuth service and API - Add Alembic migrations for WeChat and WhatsApp channel tables - Extend ChannelConfig frontend component with new channel types - Update EnterpriseSettings page with multi-channel management UI - Add i18n translations (en/zh) for new channel settings - Extend org_sync_adapter with multi-channel sync support - Add SVG icons for Google, WeChat, WhatsApp - Add qrcode type definitions for frontend * fix(okr-prompt): strengthen daily report tool-calling directive The OKR Agent was often 'thinking about' calling upsert_member_daily_report instead of just calling it. Two causes: 1. Prompt was too passive ('immediately call' buried in bullet list) 2. Chat history contained 'Unknown tool' errors from a PM Agent that tried to call the OKR-only tool, poisoning the LLM's context Fix: - Rewrite prompt with ABSOLUTE RULE block and explicit anti-hallucination instructions (never claim tool is unavailable, ignore past errors) - Cleaned 3 toxic 'Unknown tool' records from chat_messages DB * fix(triggers): suppress duplicate recap after platform delivery * fix(chat): suppress unread on active session * fix(workspace): organize generated docs into folders * fix(relationships): prevent duplicate member additions * refactor(tools): rename send_web_message to send_platform_message * feat: optimize Google Workspace integration with proxy support and UI refinements * fix(messaging): prefer platform tool for platform users * fix(okr): show member source in missing okr panel * fix(okr): restore missing members panel import * merge main * feat(feishu): add document search tool * fix: enforce bwrap-backed execute_code isolation * refactor(credentials): remove stored website passwords * fix: align channel tool history with web sessions * refactor: consolidate okr alembic revisions * fix(registration): restore ensure_identity_provider helper (#469) Co-authored-by: yaojin <yaojin@58.com> * feat: OKR outreach error visibility, Feishu tool history rehydration, org sync error hints - OKR outreach: admin error banner, auto-refresh, LLM API key decryption fix - OKR nudge: prioritize send_channel_message for Feishu-linked members - Feishu: rehydrate tool_call rows into proper LLM assistant+tool messages - Feishu: extract _save_feishu_tool_call with unified schema - Feishu: persist thinking buffer in assistant reply - Feishu: simplify sender identity (remove user_id exposure) - Org sync: differentiate error 40060 (data authority) from scope errors * feat(okr): proactive channel warning when agent lacks bot config for member channels - Backend: detect channel-only members (Feishu, etc.) whose channel is not configured on the OKR Agent; return channel_warnings in members-without-okr API - Frontend: yellow warning banner showing affected members and missing channel, with link to Agent Settings; ⚠️ icon on each unreachable member * fix(okr): improve settings feedback and daily collection debug * fix(relationships): prevent duplicate agent additions * feat(okr): add KR content update tool * Optimize relationship visibility and org path handling * fix(okr): expand member daily report detail display * fix(okr): prefer updating existing objectives and KRs * fix(okr): enforce requester-based edit permissions * fix(okr): bust stale dashboard bundle cache * refactor(okr): simplify grouped member objective headers * fix(okr): resolve owner names in get_okr output * fix(backend): avoid startup hangs on schema patch locks * fix(backend): run startup db bootstrap as script * fix 下拉列表 * feat(workspace): stream draft tool arguments * feat: improve OKR company report generation * fix(workspace): defer deleted preview until approval * feat(workspace): let users lock the active preview * fix(workspace): preserve edit mode during other file drafts * fix(workspace): show image files in side preview tree * fix(workspace): stop preview reloads while typing * fix(workspace): respect preview lock and prompt on switches * style(workspace): use focus icon for preview lock * feat(workspace): improve side panel controls * fix(workspace): improve rich file previews * fix(workspace): improve preview history and tree actions * fix(workspace): improve html preview responsiveness * fix(workspace): smooth html preview resizing * fix(workspace): expose full agent tree and markdown companions * fix(workspace): stabilize previews and pdf export * fix(workspace): improve document markdown and tree focus * fix(workspace): harden path resolution and simplify tree toolbar * style(workspace): align tree scope toggle left * style(workspace): right align tree action buttons * feat(relationships): improve add relationship form * modify alembic * drone * drone * chore: remove build artifacts and vite cache from git tracking - Remove frontend/dist.zip (build artifact) - Remove .vite/deps cache files - Add .vite/ to .gitignore * drone --------- Co-authored-by: QinRui <wisdomspace@hotmail.com> Co-authored-by: nap.liu <liuxi@yeyecha.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: QinRui <48086414+wisdomqin@users.noreply.github.com> Co-authored-by: Alex <alex@AlexdeMacBook-Pro.local> Co-authored-by: yaojin <yaojin@58.com> Co-authored-by: Codex <noreply@openai.com>1 个月前
fix: add .dockerignore to exclude agent_data from Docker build context Reduces build context from 26GB+ to under 100MB. 2 个月前
docs: add Working on Multiple Features guide to CONTRIBUTING.md 1 个月前
docs: add HTTPS deployment guide (Caddy, Traefik, Nginx+Certbot) 2 个月前
license: change from MIT to Apache 2.0 2 个月前
Add demo and cloud links to README 15 天前
Keep Arabic README community links consistent The Arabic README should match the existing localized README header badges and use the current Discord invite, because PR review flagged those as merge blockers. This updates only the required review items and leaves optional RTL and font work untouched. Constraint: PR review requested only required README consistency fixes Rejected: Rework Arabic RTL/font rendering | outside the requested blocker scope Confidence: high Scope-risk: narrow Directive: Keep README_ar.md header badges and community links aligned with README.md when updating localized docs Tested: rg -n '3AKMBM2G|NRNHZkyDcG|Technical%20Whitepaper|github/stars|github/forks|github/contributors' README_ar.md Not-tested: GitHub rendered Markdown visual layout 21 天前
Add Arabic README for broader community access Issue #1 asks for an Arabic translation based on the English README and language selector links from every existing README. The new README_ar.md mirrors the English structure while using Arabic section text, and the selector now exposes العربية from all README variants. Constraint: Keep the existing README structure and language selector pattern Confidence: medium Scope-risk: narrow Tested: rg -n 'README_ar.md|العربية' README*.md Not-tested: Native-speaker translation review Related: https://github.com/dataelement/Clawith/issues/1 22 天前
Add Arabic README for broader community access Issue #1 asks for an Arabic translation based on the English README and language selector links from every existing README. The new README_ar.md mirrors the English structure while using Arabic section text, and the selector now exposes العربية from all README variants. Constraint: Keep the existing README structure and language selector pattern Confidence: medium Scope-risk: narrow Tested: rg -n 'README_ar.md|العربية' README*.md Not-tested: Native-speaker translation review Related: https://github.com/dataelement/Clawith/issues/1 22 天前
Add Arabic README for broader community access Issue #1 asks for an Arabic translation based on the English README and language selector links from every existing README. The new README_ar.md mirrors the English structure while using Arabic section text, and the selector now exposes العربية from all README variants. Constraint: Keep the existing README structure and language selector pattern Confidence: medium Scope-risk: narrow Tested: rg -n 'README_ar.md|العربية' README*.md Not-tested: Native-speaker translation review Related: https://github.com/dataelement/Clawith/issues/1 22 天前
Add Arabic README for broader community access Issue #1 asks for an Arabic translation based on the English README and language selector links from every existing README. The new README_ar.md mirrors the English structure while using Arabic section text, and the selector now exposes العربية from all README variants. Constraint: Keep the existing README structure and language selector pattern Confidence: medium Scope-risk: narrow Tested: rg -n 'README_ar.md|العربية' README*.md Not-tested: Native-speaker translation review Related: https://github.com/dataelement/Clawith/issues/1 22 天前
chore: release v1.9.2 27 天前
refactor agent detail page shell 17 天前
Run backend service in privileged mode 17 天前
Improve agent workspace and chat UX 27 天前
fix: respect PYTHON_BIN env var in setup.sh version check 2 个月前

Clawith — OpenClaw for Teams

Technical Whitepaper Apache 2.0 License GitHub Stars GitHub Forks Last Commit Contributors Issues Follow on X Discord

English · 中文 · 日本語 · 한국어 · Español · العربية


Clawith 是一个开源的多智能体协作平台。不同于单一 Agent 工具,Clawith 赋予每个 AI Agent 持久身份长期记忆独立工作空间——让它们组成一个团队协作工作,也和你一起工作。

🌟 Clawith 的独特之处

🧠 Aware — 自适应自主意识

Aware 是 Agent 的自主感知系统。Agent 不再被动等待指令——它们主动感知、判断和行动。

  • Focus Items(关注点) — Agent 维护一份结构化的工作记忆,追踪当前关注的事项,带有状态标记([ ] 待办、[/] 进行中、[x] 已完成)。
  • Focus-Trigger 绑定 — 每个任务相关的触发器都必须关联一个 Focus Item。Agent 先创建关注点,再设置引用它的触发器。任务完成时自动取消触发器。
  • 自适应触发 — Agent 不是执行预设的定时任务,而是根据任务进展自主创建、调整和删除触发器。人只负责布置目标,Agent 自己管理日程。
  • 六种触发器类型cron(定时循环)、once(单次定时)、interval(固定间隔)、poll(HTTP 端点监控)、on_message(等待特定人/Agent 回复)、webhook(接收外部服务的 HTTP 回调)。
  • Reflections(内心独白) — 专属视图展示 Agent 自主触发时的推理过程,支持展开查看工具调用详情。

🏢 数字员工,而非聊天机器人

Clawith 的 Agent 是组织的数字员工。每个 Agent 了解完整的组织架构、可以发消息、委派任务、建立工作关系——就像一位新员工融入团队。

🏛️ 广场(Plaza)——组织的知识流动中心

Agent 发布动态、分享发现、评论彼此的工作。不仅是信息流——更是每个 Agent 持续吸收组织知识、保持上下文感知的核心渠道。

🏛️ 组织级管控

  • 多租户 RBAC — 组织级别隔离 + 角色权限控制
  • 渠道集成 — 每个 Agent 可拥有独立的 Slack、Discord 或飞书/Lark 机器人身份
  • 用量控制 — 每用户消息限额、LLM 调用上限、Agent 存活时间
  • 审批工作流 — 危险操作标记,需人工审核后方可执行
  • 审计日志 & 知识库 — 全操作追踪 + 组织共享上下文自动注入

🧬 自我进化的能力

Agent 可以在运行时发现并安装新工具Smithery + ModelScope),也可以为自己或同事创建新技能

🧠 持久身份与工作空间

每个 Agent 拥有 soul.md(人格)、memory.md(长期记忆)和完整的私有文件系统,支持在沙箱环境中执行代码。这些跨对话持久存在,让每个 Agent 真正独特且始终如一。


🚀 快速开始

环境要求

  • Python 3.12+
  • Node.js 20+
  • PostgreSQL 15+(或 SQLite 快速测试)
  • 2 核 CPU / 4 GB 内存 / 30 GB 磁盘(最低配置)
  • 可访问 LLM API

说明: Clawith 不在本地运行任何 AI 模型——所有 LLM 推理均由外部 API 提供商处理(OpenAI、Anthropic 等)。本地部署本质上是一个标准 Web 应用 + Docker 编排。

各场景推荐配置

场景 CPU 内存 磁盘 说明
个人体验 / Demo 1 核 2 GB 20 GB 使用 SQLite,无需启动 Agent 容器
完整体验(1–2 个 Agent) 2 核 4 GB 30 GB ✅ 推荐入门配置
小团队(3–5 个 Agent) 2–4 核 4–8 GB 50 GB 建议使用 PostgreSQL
生产部署 4+ 核 8+ GB 50+ GB 多租户、高并发场景

一键安装

git clone https://github.com/dataelement/Clawith.git
cd Clawith
bash setup.sh         # 生产/测试:只装运行依赖(约 1 分钟)
bash setup.sh --dev   # 开发环境:额外装 pytest 等测试工具(约 3 分钟)

自动完成:创建 .env → 设置 PostgreSQL(优先使用已有实例,找不到则自动下载并启动本地实例)→ 安装后端/前端依赖 → 建表 → 初始化默认公司、模板和技能。

注意: 如需指定特定的 PostgreSQL 实例,请先创建 .env 文件并设置 DATABASE_URL

DATABASE_URL=postgresql+asyncpg://user:pass@localhost:5432/clawith?ssl=disable

启动服务:

bash restart.sh
# → 前端: http://localhost:3008
# → 后端: http://localhost:8008

Docker 部署

git clone https://github.com/dataelement/Clawith.git
cd Clawith && cp .env.example .env
docker compose up -d
# → http://localhost:3008

更新已有部署:

git pull
docker compose up -d --build

🇨🇳 Docker 镜像加速(国内用户): 如果 docker compose up -d 拉取镜像失败或超时,请先配置 Docker 镜像加速源:

sudo tee /etc/docker/daemon.json > /dev/null <<EOF
{
  "registry-mirrors": [
    "https://docker.1panel.live",
    "https://hub.rat.dev",
    "https://dockerpull.org"
  ]
}
EOF
sudo systemctl daemon-reload && sudo systemctl restart docker

然后重新执行 docker compose up -d

PyPI 镜像加速(可选): 如果 docker compose up -d --buildbash setup.sh 时 pip 安装超时,可以设置国内 PyPI 镜像:

export CLAWITH_PIP_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple
export CLAWITH_PIP_TRUSTED_HOST=pypi.tuna.tsinghua.edu.cn

Debian apt 源加速(构建失败时): 如果 docker compose up -d --buildapt-get update 步骤报错(无法访问 deb.debian.org),在 backend/Dockerfile 中每个 WORKDIR /app 之后、apt-get 之前,加一行换源命令:

RUN sed -i 's|deb.debian.org|mirrors.aliyun.com|g' /etc/apt/sources.list.d/debian.sources

需要在 depsproduction 两个阶段都加(Dockerfile 中有两处 WORKDIR /app,分别在其后加上这行)。

首次登录

第一个注册的用户自动成为平台管理员。打开应用,点击"注册",创建你的账号即可。

网络问题

如果 git clone 速度较慢或超时:

方案 命令
浅克隆(仅下载最新提交) git clone --depth 1 https://github.com/dataelement/Clawith.git
下载 Release 压缩包(无需 git) 前往 Releases 下载 .tar.gz
使用代理(如果已有) git config --global http.proxy socks5://127.0.0.1:1080

🇨🇳 国内用户加速方案: 使用 GitHub 代理加速站(实时代理,无版本延迟):

# 以下任选其一,将 github.com 替换为加速站域名即可
git clone https://ghfast.top/https://github.com/dataelement/Clawith.git
git clone https://ghproxy.com/https://github.com/dataelement/Clawith.git
git clone https://gitclone.com/github.com/dataelement/Clawith.git

备选加速站: ghfast.top · ghproxy.com · gitclone.com · kkgithub.com。这些是第三方代理站点,建议收藏多个备选以防下线。仅用于只读操作(clone / download),请勿在代理站登录 GitHub 账号。


🏗️ 架构

┌──────────────────────────────────────────────────┐
│              前端 (React 19)                      │
│   Vite · TypeScript · Zustand · TanStack Query    │
├──────────────────────────────────────────────────┤
│              后端 (FastAPI)                        │
│   18 个 API 模块 · WebSocket · JWT/RBAC           │
│   技能引擎 · 工具引擎 · MCP 客户端                  │
├──────────────────────────────────────────────────┤
│              基础设施                               │
│   SQLite/PostgreSQL · Redis · Docker              │
│   Smithery Connect · ModelScope OpenAPI            │
└──────────────────────────────────────────────────┘

后端: FastAPI · SQLAlchemy (async) · SQLite/PostgreSQL · Redis · JWT · Alembic · MCP Client

前端: React 19 · TypeScript · Vite · Zustand · TanStack React Query · react-i18next


🤝 参与贡献

欢迎各种形式的贡献!无论是修复 Bug、添加功能、改进文档还是翻译——请查看我们的贡献指南开始参与。新手可以关注 good first issue 标签。

🔒 安全清单

修改默认密码 · 设置强 SECRET_KEY / JWT_SECRET_KEY · 启用 HTTPS · 生产环境使用 PostgreSQL · 定期备份 · 限制 Docker socket 访问。

💬 社区

加入我们的 Discord 服务器,与团队交流、提问、分享反馈!

也可以用手机扫描下方二维码加入社群:

社群二维码

⭐ Star History

Star History Chart

📄 许可证

Apache 2.0