agent-network
Multi-Agent group chat collaboration system inspired by DingTalk/Lark. Enables AI agents to chat in groups, @mention each other, assign tasks, make decisions via voting, and collaborate. Use when building multi-agent systems that need structured communication, task delegation, de
Install
npx skills add https://github.com/aAAaqwq/AGI-Super-Team/tree/main/skills/agent-network
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install aaaaqwq-agi-super-team@llmmart
git clone https://github.com/aAAaqwq/AGI-Super-Team.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole aaaaqwq/agi-super-team collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
Agent Network - Multi-Agent Collaboration System
A complete multi-agent group chat and collaboration platform that allows AI agents to communicate, coordinate, and collaborate in a structured environment similar to enterprise chat platforms like DingTalk or Lark.
What This Skill Provides
- Group Chat System - Multiple agents can chat in groups with message history
- @Mentions - Agents can @mention each other to trigger notifications
- Task Management - Create, assign, track, and complete tasks
- Decision Voting - Propose decisions and vote (for/against/abstain)
- Inbox Notifications - Unread message tracking and notification center
- Online Status - Real-time agent online/offline status
- Central Coordinator - Message routing and agent lifecycle management
Quick Start
from agent_network import AgentManager, GroupManager, MessageManager, TaskManager, DecisionManager, get_coordinator
# Initialize default agents
from agent_network import init_default_agents
init_default_agents()
# Get the coordinator
coordinator = get_coordinator()
# Register agents
coordinator.register_agent(agent_id=1)
coordinator.register_agent(agent_id=2)
# Create a group
group = GroupManager.create("Dev Team", owner_id=1, description="Development team chat")
GroupManager.add_member(group.id, agent_id=2)
# Send a message with @mention
MessageManager.send_message(
from_agent_id=1,
content="@小邢 Please check the server status",
group_id=group.id
)
# Assign a task
task = TaskManager.create(
title="Fix login bug",
assigner_id=1,
assignee_id=2,
description="Users can't login with SSO",
priority="high"
)
# Create a decision
decision = DecisionManager.create(
title="Adopt new database?",
description="Should we migrate to distributed database?",
proposer_id=1,
group_id=group.id
)
# Vote on decision
DecisionManager.vote(decision.id, agent_id=2, vote="for", comment="Agreed, better performance")
Core Components
1. Agent Management (agent_manager.py)
Register and manage agents with online/offline status:
from agent_network import AgentManager
# Register new agent
agent = AgentManager.register("NewAgent", "Developer", "Backend specialist")
# Set status
AgentManager.go_online(agent.id)
AgentManager.go_offline(agent.id)
# Get online agents
online = AgentManager.get_online_agents()
2. Group Management (group_manager.py)
Create groups and manage membership:
from agent_network import GroupManager
# Create group
group = GroupManager.create("Project Alpha", owner_id=1)
# Add members
GroupManager.add_member(group.id, agent_id=2)
GroupManager.add_member(group.id, agent_id=3)
# List members
members = GroupManager.get_members(group.id)
online_members = GroupManager.list_online_members(group.id)
3. Message System (message_manager.py)
Send messages with @mention support:
from agent_network import MessageManager
# Send message
msg = MessageManager.send_message(
from_agent_id=1,
content="Hello team!",
group_id=1
)
# @mention automatically detected
msg = MessageManager.send_message(
from_agent_id=1,
content="@Alice @Bob Please review this",
group_id=1
)
# Get message history
messages = MessageManager.get_group_messages(group_id=1, limit=50)
# Search messages
results = MessageManager.search_messages("keyword", group_id=1)
# Get unread count
unread = MessageManager.get_unread_count(agent_id=1)
inbox = MessageManager.get_agent_inbox(agent_id=1, only_unread=True)
4. Task Management (task_manager.py)
Full task lifecycle:
from agent_network import TaskManager
# Create task
task = TaskManager.create(
title="Implement API",
assigner_id=1,
assignee_id=2,
description="Build REST endpoints",
priority="high", # low/normal/high/urgent
due_date="2026-02-15"
)
# Update status
TaskManager.start_task(task.id, agent_id=2)
TaskManager.complete_task(task.id, agent_id=2, result="All tests passed")
# Add comments
TaskManager.add_comment(task.id, agent_id=2, "50% complete")
# List tasks
all_tasks = TaskManager.get_all()
my_tasks = TaskManager.get_agent_tasks(agent_id=2, status="pending")
5. Decision Voting (decision_manager.py)
Collaborative decision making:
from agent_network import DecisionManager
# Create proposal
decision = DecisionManager.create(
title="Use microservices?",
description="Should we refactor to microservices?",
proposer_id=1,
group_id=1
)
# Vote
DecisionManager.vote(decision.id, agent_id=2, vote="for", comment="Better scalability")
DecisionManager.vote(decision.id, agent_id=3, vote="against")
# Update status
DecisionManager.update_status(decision.id, "approved", updater_id=1)
# Check results
decision = DecisionManager.get_by_id(decision.id)
print(f"Pass rate: {decision.pass_rate}%")
6. Central Coordinator (coordinator.py)
High-level coordination with automatic message routing:
from agent_network import get_coordinator
coord = get_coordinator()
# Register with message handler
def my_handler(msg_dict):
print(f"Received: {msg_dict['content']}")
coord.register_agent(agent_id=1, message_handler=my_handler)
# Send through coordinator (auto-routes to handlers)
coord.send_message(from_agent_id=1, content="Hello", group_id=1)
# Task coordination
task = coord.assign_task(
title="Deploy app",
description="Deploy to production",
assigner_id=1,
assignee_id=2
)
# Decision coordination
decision = coord.propose_decision(
title="Release v2.0?",
description="Ready for release?",
proposer_id=1
)
coord.vote_decision(decision['id'], agent_id=2, vote="for")
CLI Usage
Interactive CLI for testing:
# Run demo
python demo.py
# Interactive CLI
python cli.py
# Commands in CLI:
# - Select agent to login
# - Enter groups to chat
# - Type /task to create tasks
# - Type /decision to create votes
# - Type @AgentName to mention
Default Agents
Six pre-configured agents:
| Agent | Role | Description |
|---|---|---|
| 老邢 (Lao Xing) | Manager | Overall coordination |
| 小邢 (Xiao Xing) | DevOps | Development and operations |
| 小金 (Xiao Jin) | Finance Analyst | Market analysis |
| 小陈 (Xiao Chen) | Trader | Trading execution |
| 小影 (Xiao Ying) | Designer | Design and content |
| 小视频 (Xiao Shipin) | Video | Video production |
Database Schema
SQLite database with tables:
agents- Agent profiles and statusgroups- Group definitionsgroup_members- Membership relationsmessages- Chat messages with typestasks- Task trackingtask_comments- Task discussionsdecisions- Decision proposalsdecision_votes- Voting recordsagent_inbox- Notification inbox
Integration with OpenClaw
Use with sessions_spawn for true multi-agent workflows:
# When a task is assigned, spawn a sub-agent
if new_task:
sessions_spawn(
agentId="xiaoxing",
task=new_task.description,
label=f"task-{new_task.task_id}"
)
Files Reference
scripts/agent_network/- Python modules__init__.py- Package exportsdatabase.py- SQLite managementagent_manager.py- Agent CRUDgroup_manager.py- Group managementmessage_manager.py- Messaging systemtask_manager.py- Task managementdecision_manager.py- Voting systemcoordinator.py- Central coordinator
scripts/cli.py- Interactive CLIscripts/demo.py- Demo scriptreferences/schema.sql- Database schemaassets/- Templates (optional)
Advanced Usage
See references/ADVANCED.md for:
- Custom agent handlers
- Webhook integrations
- Message filtering
- Custom workflows
Files (agi-super-team)
-
.clawhub
-
origin.json 145 B
{ "version": 1, "registry": "https://clawhub.ai", "slug": "agent-network", "installedVersion": "1.1.0", "installedAt": 1777595359466 }
-
-
references
-
ADVANCED.md 11.4 KB
# Advanced Usage Guide for Agent Network ## Custom Agent Message Handlers Register agents with custom handlers for true automation: ```python from agent_network import get_coordinator, AgentManager def create_smart_handler(agent_name, capabilities): """Create a handler that responds based on agent capabilities""" def handler(msg_dict): content = msg_dict.get('content', '') from_agent = msg_dict.get('from_agent_name', 'Unknown') msg_type = msg_dict.get('type', 'chat') # Check if this agent is mentioned if f'@{agent_name}' in content: print(f"[{agent_name}] I was mentioned by {from_agent}!") # Auto-respond based on message type if 'task' in content.lower() and 'dev' in capabilities: print(f"[{agent_name}] 📋 Task-related message detected") elif 'analyze' in content.lower() and 'finance' in capabilities: print(f"[{agent_name}] 📊 Analysis request detected") elif 'design' in content.lower() and 'design' in capabilities: print(f"[{agent_name}] 🎨 Design request detected") return handler # Register with smart handlers coord = get_coordinator() dev_agent = AgentManager.get_by_name("小邢") if dev_agent: coord.register_agent( dev_agent.id, message_handler=create_smart_handler("小邢", ["dev", "ops"]) ) finance_agent = AgentManager.get_by_name("小金") if finance_agent: coord.register_agent( finance_agent.id, message_handler=create_smart_handler("小金", ["finance", "analyze"]) ) ``` ## Webhook Integration Integrate with external systems via webhooks: ```python import requests from agent_network import get_coordinator class WebhookNotifier: def __init__(self, webhook_url): self.webhook_url = webhook_url self.coord = get_coordinator() def notify_on_mention(self, msg_dict): """Send webhook when agent is mentioned""" content = msg_dict.get('content', '') if '@' in content: # Someone was mentioned payload = { 'event': 'agent_mentioned', 'from': msg_dict.get('from_agent_name'), 'content': content, 'timestamp': msg_dict.get('created_at'), 'group': msg_dict.get('group_name') } try: requests.post(self.webhook_url, json=payload, timeout=5) except Exception as e: print(f"Webhook failed: {e}") def register(self, agent_id): """Register webhook handler for an agent""" self.coord.register_agent(agent_id, self.notify_on_mention) # Usage notifier = WebhookNotifier("https://hooks.slack.com/services/...") notifier.register(agent_id=1) ``` ## Message Filtering and Routing Custom message routing logic: ```python from agent_network import MessageManager, AgentManager class MessageRouter: """Advanced message routing with filtering""" def __init__(self): self.filters = [] self.routes = {} def add_filter(self, keyword, target_agent_id): """Route messages containing keyword to specific agent""" self.filters.append((keyword, target_agent_id)) def route_message(self, msg_dict): """Apply routing rules to message""" content = msg_dict.get('content', '').lower() for keyword, target_id in self.filters: if keyword.lower() in content: # Create inbox notification for target agent MessageManager.create_inbox_notification( target_id, msg_dict.get('id') ) print(f"Routed message to agent {target_id} (matched: {keyword})") def auto_assign_tasks(self, msg_dict): """Auto-create tasks from certain message patterns""" content = msg_dict.get('content', '') # Pattern: "URGENT: ..." -> Create high priority task if content.upper().startswith('URGENT:'): from_agent_id = msg_dict.get('from_agent_id') # Find online DevOps agent online_agents = AgentManager.get_online_agents() dev_agent = next( (a for a in online_agents if 'dev' in a.role.lower()), None ) if dev_agent: from agent_network import TaskManager TaskManager.create( title=content[7:50], # Remove "URGENT:" and truncate assigner_id=from_agent_id, assignee_id=dev_agent.id, description=content, priority="urgent" ) print(f"Auto-created urgent task for {dev_agent.name}") # Usage router = MessageRouter() router.add_filter("bug", target_agent_id=2) router.add_filter("server down", target_agent_id=2) router.add_filter("market crash", target_agent_id=3) ``` ## Custom Workflows Build complex multi-agent workflows: ```python from agent_network import ( get_coordinator, GroupManager, TaskManager, DecisionManager, AgentManager ) import time class DeploymentWorkflow: """Automated deployment workflow with approvals""" def __init__(self): self.coord = get_coordinator() self.group = None def setup(self): """Create deployment group""" manager = AgentManager.get_by_name("老邢") dev = AgentManager.get_by_name("小邢") self.group = GroupManager.create( "🚀 Deployment Team", owner_id=manager.id, description="Production deployment coordination" ) GroupManager.add_member(self.group.id, dev.id) return self.group def start_deployment(self, version): """Start deployment workflow""" manager = AgentManager.get_by_name("老邢") # Step 1: Create decision for approval decision = DecisionManager.create( title=f"Deploy v{version} to Production?", description=f"Ready to deploy version {version}. All tests passed.", proposer_id=manager.id, group_id=self.group.id ) print(f"📊 Deployment decision created: {decision.decision_id}") print("Waiting for votes...") return decision def on_decision_approved(self, decision_id, version): """Callback when deployment is approved""" manager = AgentManager.get_by_name("老邢") dev = AgentManager.get_by_name("小邢") # Step 2: Create deployment task task = TaskManager.create( title=f"Deploy v{version}", assigner_id=manager.id, assignee_id=dev.id, description=f"Execute production deployment for v{version}", group_id=self.group.id, priority="high" ) print(f"📋 Deployment task created: {task.task_id}") # Step 3: Auto-start task TaskManager.start_task(task.id, dev.id) print("🚀 Deployment started!") return task def complete_deployment(self, task_id, version): """Mark deployment complete""" dev = AgentManager.get_by_name("小邢") TaskManager.complete_task( task_id, dev.id, result=f"v{version} successfully deployed" ) # Broadcast success self.coord.broadcast_system_message( f"🎉 v{version} is now live!", group_id=self.group.id ) # Usage workflow = DeploymentWorkflow() group = workflow.setup() decision = workflow.start_deployment("2.5.0") # Later, when decision is approved: # workflow.on_decision_approved(decision.id, "2.5.0") ``` ## Scheduled Tasks with Cron Integrate with cron for scheduled operations: ```python from datetime import datetime, timedelta from agent_network import TaskManager, AgentManager class ScheduledTaskManager: """Manage recurring tasks""" def __init__(self): self.scheduled = [] def schedule_daily_report(self, assignee_name="小金"): """Schedule daily market report task""" agent = AgentManager.get_by_name(assignee_name) if not agent: return # Create task for tomorrow morning tomorrow = (datetime.now() + timedelta(days=1)).strftime("%Y-%m-%d") task = TaskManager.create( title=f"Daily Market Report - {tomorrow}", assigner_id=agent.id, # Self-assigned assignee_id=agent.id, description="Generate and distribute daily market analysis", due_date=tomorrow, priority="normal" ) print(f"📅 Scheduled daily report: {task.task_id}") return task def schedule_weekly_review(self, group_id=None): """Schedule weekly team review""" manager = AgentManager.get_by_name("老邢") # Find next Friday today = datetime.now() friday = today + timedelta(days=(4 - today.weekday()) % 7) task = TaskManager.create( title=f"Weekly Team Review - Week {friday.isocalendar()[1]}", assigner_id=manager.id, assignee_id=manager.id, description="Review team progress and plan next week", due_date=friday.strftime("%Y-%m-%d"), priority="normal", group_id=group_id ) print(f"📅 Scheduled weekly review: {task.task_id}") return task # Usage with OpenClaw cron # cron.add(job={...}) to schedule these daily/weekly ``` ## Persistence and State Management Handle agent state across sessions: ```python import json import os from agent_network import AgentManager class AgentStateManager: """Persist agent states to disk""" def __init__(self, state_dir="./agent_states"): self.state_dir = state_dir os.makedirs(state_dir, exist_ok=True) def save_state(self, agent_id, state_dict): """Save agent state""" filepath = os.path.join(self.state_dir, f"agent_{agent_id}.json") with open(filepath, 'w') as f: json.dump(state_dict, f, indent=2) def load_state(self, agent_id): """Load agent state""" filepath = os.path.join(self.state_dir, f"agent_{agent_id}.json") if os.path.exists(filepath): with open(filepath, 'r') as f: return json.load(f) return {} def restore_all_agents(self): """Restore all agent states from disk""" for filename in os.listdir(self.state_dir): if filename.startswith("agent_") and filename.endswith(".json"): agent_id = int(filename.split("_")[1].split(".")[0]) state = self.load_state(agent_id) # Restore status if state.get('status') == 'online': AgentManager.go_online(agent_id) print(f"Restored state for agent {agent_id}") # Usage state_mgr = AgentStateManager() # Before shutdown, save states for agent in AgentManager.get_all(): state_mgr.save_state(agent.id, { 'status': agent.status, 'last_active': agent.last_active, 'current_tasks': [...] }) # On startup, restore state_mgr.restore_all_agents() ``` -
schema.sql 5.8 KB · in bundle
-
-
scripts
-
agent_network
-
agent_manager.py 4.8 KB
#!/usr/bin/env python3 """ Agent 群聊协作系统 - Agent 管理模块 负责 Agent 的注册、登录、状态管理等 """ from datetime import datetime from typing import Optional, List, Dict, Any import sqlite3 import sys import os sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) try: from database import db except ImportError: from .database import db class Agent: """Agent 类""" def __init__(self, id: int = None, agent_id: int = None, name: str = "", role: str = "", description: str = "", status: str = "offline", created_at: str = "", last_active: str = "", **kwargs): self.id = id if id is not None else agent_id self.name = name self.role = role self.description = description self.status = status self.created_at = created_at self.last_active = last_active def to_dict(self) -> Dict[str, Any]: return { 'id': self.id, 'name': self.name, 'role': self.role, 'description': self.description, 'status': self.status, 'created_at': self.created_at, 'last_active': self.last_active } def __repr__(self): return f"Agent({self.name} - {self.role})" class AgentManager: """Agent 管理器""" @staticmethod def register(name: str, role: str, description: str = "") -> Optional[Agent]: """注册新 Agent""" try: agent_id = db.insert( "INSERT INTO agents (name, role, description, status, last_active) VALUES (?, ?, ?, 'offline', ?)", (name, role, description, datetime.now().isoformat()) ) return AgentManager.get_by_id(agent_id) except sqlite3.IntegrityError: print(f"Agent '{name}' 已存在") return None @staticmethod def get_by_id(agent_id: int) -> Optional[Agent]: """通过 ID 获取 Agent""" row = db.fetch_one("SELECT * FROM agents WHERE id = ?", (agent_id,)) if row: return Agent(**row) return None @staticmethod def get_by_name(name: str) -> Optional[Agent]: """通过名称获取 Agent""" row = db.fetch_one("SELECT * FROM agents WHERE name = ?", (name,)) if row: return Agent(**row) return None @staticmethod def get_all() -> List[Agent]: """获取所有 Agent""" rows = db.fetch_all("SELECT * FROM agents ORDER BY created_at") return [Agent(**row) for row in rows] @staticmethod def update_status(agent_id: int, status: str) -> bool: """更新 Agent 状态""" valid_status = ['online', 'offline', 'busy'] if status not in valid_status: return False affected = db.execute( "UPDATE agents SET status = ?, last_active = ? WHERE id = ?", (status, datetime.now().isoformat(), agent_id) ) return affected > 0 @staticmethod def go_online(agent_id: int) -> bool: """Agent 上线""" return AgentManager.update_status(agent_id, 'online') @staticmethod def go_offline(agent_id: int) -> bool: """Agent 下线""" return AgentManager.update_status(agent_id, 'offline') @staticmethod def set_busy(agent_id: int) -> bool: """设置 Agent 忙碌状态""" return AgentManager.update_status(agent_id, 'busy') @staticmethod def delete(agent_id: int) -> bool: """删除 Agent""" affected = db.execute("DELETE FROM agents WHERE id = ?", (agent_id,)) return affected > 0 @staticmethod def get_online_agents() -> List[Agent]: """获取在线 Agent 列表""" rows = db.fetch_all("SELECT * FROM agents WHERE status = 'online' ORDER BY last_active DESC") return [Agent(**row) for row in rows] # 初始化默认 Agent 列表 def init_default_agents(): """初始化默认 Agent""" default_agents = [ ("老邢", "总管", "负责整体协调和决策"), ("小邢", "开发运维", "负责系统开发和运维"), ("小金", "金融市场分析", "负责金融市场分析和研究"), ("小陈", "美股交易", "负责美股交易执行"), ("小影", "设计/短视频", "负责设计和短视频内容"), ("小视频", "视频制作", "负责视频制作和后期"), ] for name, role, desc in default_agents: agent = AgentManager.get_by_name(name) if not agent: AgentManager.register(name, role, desc) print(f"已创建 Agent: {name} ({role})") if __name__ == "__main__": init_default_agents() print("\n所有 Agent 列表:") for agent in AgentManager.get_all(): print(f" - {agent}") -
coordinator.py 12.8 KB
#!/usr/bin/env python3 """ Agent 群聊协作系统 - 中央协调器 负责系统整体协调、消息路由、Agent 调度等 """ import os import sys import json import time import threading from datetime import datetime from typing import Optional, List, Dict, Any, Callable from dataclasses import dataclass, field # 添加父目录到路径 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from database import Database, db from agent_manager import AgentManager, Agent from message_manager import MessageManager, Message, MessageFormatter from group_manager import GroupManager, Group from task_manager import TaskManager, TaskStatus, TaskPriority from decision_manager import DecisionManager, DecisionStatus, VoteType @dataclass class AgentSession: """Agent 会话状态""" agent: Agent last_heartbeat: float = field(default_factory=time.time) is_active: bool = True current_group_id: Optional[int] = None handler: Optional[Callable] = None class Coordinator: """ Agent 群聊协作系统中央协调器 负责: 1. Agent 生命周期管理 2. 消息路由和分发 3. @提及通知处理 4. 任务调度 5. 决策流程管理 """ _instance = None def __new__(cls): if cls._instance is None: cls._instance = super().__new__(cls) cls._instance._initialized = False return cls._instance def __init__(self): if self._initialized: return self._initialized = True self.sessions: Dict[int, AgentSession] = {} # agent_id -> session self.message_handlers: Dict[int, List[Callable]] = {} # agent_id -> handlers self.running = False self.coordinator_thread = None self.check_interval = 5 # 心跳检查间隔(秒) # 确保默认 Agent 存在 self._init_default_agents() def _init_default_agents(self): """初始化默认 Agent""" default_agents = [ ("老邢", "总管", "负责整体协调和决策"), ("小邢", "开发运维", "负责系统开发和运维"), ("小金", "金融市场分析", "负责金融市场分析和研究"), ("小陈", "美股交易", "负责美股交易执行"), ("小影", "设计/短视频", "负责设计和短视频内容"), ("小视频", "视频制作", "负责视频制作和后期"), ] for name, role, desc in default_agents: agent = AgentManager.get_by_name(name) if not agent: AgentManager.register(name, role, desc) print(f"[协调器] 已创建 Agent: {name} ({role})") def register_agent(self, agent_id: int, message_handler: Optional[Callable] = None) -> bool: """注册 Agent 到协调器""" agent = AgentManager.get_by_id(agent_id) if not agent: print(f"[协调器] Agent {agent_id} 不存在") return False # 更新状态为在线 AgentManager.go_online(agent_id) # 创建会话 session = AgentSession(agent=agent, handler=message_handler) self.sessions[agent_id] = session # 注册消息处理器 if message_handler: if agent_id not in self.message_handlers: self.message_handlers[agent_id] = [] self.message_handlers[agent_id].append(message_handler) print(f"[协调器] Agent '{agent.name}' 已注册并上线") # 发送系统通知 self.broadcast_system_message(f"Agent '{agent.name}' 已上线") return True def unregister_agent(self, agent_id: int) -> bool: """从协调器注销 Agent""" if agent_id not in self.sessions: return False agent_name = self.sessions[agent_id].agent.name # 更新状态为离线 AgentManager.go_offline(agent_id) # 移除会话 del self.sessions[agent_id] if agent_id in self.message_handlers: del self.message_handlers[agent_id] print(f"[协调器] Agent '{agent_name}' 已注销") # 发送系统通知 self.broadcast_system_message(f"Agent '{agent_name}' 已下线") return True def send_message(self, from_agent_id: int, content: str, group_id: Optional[int] = None, to_agent_id: Optional[int] = None, msg_type: str = "chat") -> Optional[Message]: """发送消息""" # 验证发送者 if from_agent_id not in self.sessions: print(f"[协调器] Agent {from_agent_id} 未注册") return None # 发送消息 msg = MessageManager.send_message( from_agent_id=from_agent_id, content=content, group_id=group_id, to_agent_id=to_agent_id, msg_type=msg_type ) if msg: # 触发消息处理 self._route_message(msg) return msg def _route_message(self, msg: Message): """路由消息到相关 Agent""" # 获取消息中 @提及的 Agent mentioned_agents = MessageManager.detect_mentions(msg.content) # 通知被 @提及的 Agent for agent in mentioned_agents: if agent.id in self.sessions: self._notify_agent(agent.id, msg) # 如果是私信,通知接收者 if msg.to_agent_id and msg.to_agent_id in self.sessions: self._notify_agent(msg.to_agent_id, msg) # 触发处理器 handlers_to_call = [] # 收集相关处理器 for agent_id, handlers in self.message_handlers.items(): if agent_id == msg.from_agent_id: continue # 不通知发送者自己 # 检查是否是目标接收者 should_notify = False if msg.to_agent_id and msg.to_agent_id == agent_id: should_notify = True elif any(a.id == agent_id for a in mentioned_agents): should_notify = True elif msg.group_id: # 群组消息 - 通知所有在线的群组成员 should_notify = True if should_notify: handlers_to_call.extend(handlers) # 异步调用处理器 for handler in handlers_to_call: try: threading.Thread(target=handler, args=(msg.to_dict(),), daemon=True).start() except Exception as e: print(f"[协调器] 消息处理器错误: {e}") def _notify_agent(self, agent_id: int, msg: Message): """通知特定 Agent""" if agent_id in self.sessions: session = self.sessions[agent_id] session.last_heartbeat = time.time() # 标记消息为已读(如果 Agent 在线) MessageManager.mark_as_read(agent_id, msg.id) def broadcast_system_message(self, content: str, group_id: Optional[int] = None): """广播系统消息""" # 获取系统 Agent(老邢作为总管) system_agent = AgentManager.get_by_name("老邢") if not system_agent: return MessageManager.send_message( from_agent_id=system_agent.id, content=f"[系统] {content}", group_id=group_id, msg_type="system" ) def create_group(self, name: str, owner_id: int, description: str = "") -> Optional[Group]: """创建群组""" return GroupManager.create(name, owner_id, description) def join_group(self, agent_id: int, group_id: int) -> bool: """Agent 加入群组""" return GroupManager.add_member(group_id, agent_id) def leave_group(self, agent_id: int, group_id: int) -> bool: """Agent 离开群组""" return GroupManager.remove_member(group_id, agent_id) def assign_task(self, title: str, description: str, assigner_id: int, assignee_id: int, group_id: Optional[int] = None, priority: str = "normal", due_date: Optional[str] = None) -> Optional[Dict]: """指派任务""" task = TaskManager.create( title=title, description=description, assigner_id=assigner_id, assignee_id=assignee_id, group_id=group_id, priority=priority, due_date=due_date ) return task.to_dict() if task else None def complete_task(self, task_id: str, agent_id: int, result: str = "") -> bool: """完成任务""" return TaskManager.complete_task(task_id, agent_id, result) def propose_decision(self, title: str, description: str, proposer_id: int, group_id: Optional[int] = None) -> Optional[Dict]: """提出决策""" decision = DecisionManager.propose(title, description, proposer_id, group_id) return decision.to_dict() if decision else None def vote_decision(self, decision_id: str, agent_id: int, vote: str, comment: str = "") -> bool: """投票决策""" return DecisionManager.vote(decision_id, agent_id, vote, comment) def finalize_decision(self, decision_id: str) -> Optional[Dict]: """结束决策投票""" decision = DecisionManager.finalize(decision_id) return decision.to_dict() if decision else None def get_agent_inbox(self, agent_id: int, only_unread: bool = False) -> List[Dict]: """获取 Agent 收件箱""" return MessageManager.get_agent_inbox(agent_id, only_unread) def get_unread_count(self, agent_id: int) -> int: """获取未读消息数""" return MessageManager.get_unread_count(agent_id) def get_online_agents(self) -> List[Dict]: """获取在线 Agent 列表""" agents = AgentManager.get_online_agents() return [a.to_dict() for a in agents] def start(self): """启动协调器""" if self.running: return self.running = True self.coordinator_thread = threading.Thread(target=self._run, daemon=True) self.coordinator_thread.start() print("[协调器] 已启动") def stop(self): """停止协调器""" self.running = False if self.coordinator_thread: self.coordinator_thread.join(timeout=5) print("[协调器] 已停止") def _run(self): """协调器主循环""" while self.running: time.sleep(self.check_interval) self._check_heartbeats() def _check_heartbeats(self): """检查 Agent 心跳""" current_time = time.time() timeout = 60 # 60秒无心跳视为离线 for agent_id, session in list(self.sessions.items()): if current_time - session.last_heartbeat > timeout: print(f"[协调器] Agent '{session.agent.name}' 心跳超时,标记为离线") AgentManager.go_offline(agent_id) session.is_active = False # 便捷函数 def get_coordinator() -> Coordinator: """获取协调器单例""" return Coordinator() # 用于演示的示例 Agent 处理器 def demo_message_handler(agent_name: str): """创建示例消息处理器""" def handler(msg_dict: Dict): print(f"\n[{agent_name} 收到消息]") print(f" 来自: {msg_dict.get('from_agent_name', 'Unknown')}") print(f" 内容: {msg_dict.get('content', '')[:50]}...") print(f" 类型: {msg_dict.get('type', 'chat')}") print() return handler if __name__ == "__main__": # 简单测试 coord = get_coordinator() coord.start() # 获取 Agent lao_xing = AgentManager.get_by_name("老邢") xiao_xing = AgentManager.get_by_name("小邢") if lao_xing and xiao_xing: # 注册 Agent coord.register_agent(lao_xing.id, demo_message_handler("老邢")) coord.register_agent(xiao_xing.id, demo_message_handler("小邢")) # 发送测试消息 coord.send_message(lao_xing.id, "@小邢 测试一下系统", msg_type="chat") # 创建任务 task = coord.assign_task( title="检查服务器状态", description="请检查所有服务器的运行状态", assigner_id=lao_xing.id, assignee_id=xiao_xing.id, priority="high" ) print(f"创建任务: {task}") time.sleep(2) coord.stop() -
database.py 3.3 KB
#!/usr/bin/env python3 """ Agent 群聊协作系统 - 数据库管理模块 负责数据库连接、初始化和基本操作 """ import sqlite3 import os from datetime import datetime from typing import Optional, List, Dict, Any from contextlib import contextmanager class Database: """数据库管理类""" def __init__(self, db_path: str = "data/agent_network.db"): self.db_path = db_path # 确保目录存在 os.makedirs(os.path.dirname(db_path), exist_ok=True) self.init_database() @contextmanager def get_connection(self): """获取数据库连接上下文管理器""" conn = sqlite3.connect(self.db_path) conn.row_factory = sqlite3.Row # 使结果可以通过列名访问 try: yield conn conn.commit() except Exception as e: conn.rollback() raise e finally: conn.close() def init_database(self): """初始化数据库,执行 schema.sql""" # Try multiple possible locations for schema.sql possible_paths = [ os.path.join(os.path.dirname(__file__), '..', '..', 'references', 'schema.sql'), # Skill structure os.path.join(os.path.dirname(__file__), '..', 'schema.sql'), # Local dev os.path.join(os.path.dirname(__file__), '..', '..', 'schema.sql'), # Alternate ] schema_path = None for path in possible_paths: if os.path.exists(path): schema_path = path break if os.path.exists(schema_path): with open(schema_path, 'r', encoding='utf-8') as f: schema = f.read() with self.get_connection() as conn: conn.executescript(schema) else: print(f"警告: 未找到 schema.sql 文件: {schema_path}") def execute(self, query: str, params: tuple = ()) -> int: """执行 SQL 语句,返回影响的行数""" with self.get_connection() as conn: cursor = conn.execute(query, params) return cursor.rowcount def execute_many(self, query: str, params_list: List[tuple]) -> int: """批量执行 SQL 语句""" with self.get_connection() as conn: cursor = conn.executemany(query, params_list) return cursor.rowcount def fetch_one(self, query: str, params: tuple = ()) -> Optional[Dict[str, Any]]: """查询单条记录""" with self.get_connection() as conn: cursor = conn.execute(query, params) row = cursor.fetchone() if row: return dict(row) return None def fetch_all(self, query: str, params: tuple = ()) -> List[Dict[str, Any]]: """查询多条记录""" with self.get_connection() as conn: cursor = conn.execute(query, params) rows = cursor.fetchall() return [dict(row) for row in rows] def insert(self, query: str, params: tuple = ()) -> int: """插入记录,返回自增ID""" with self.get_connection() as conn: cursor = conn.execute(query, params) return cursor.lastrowid # 全局数据库实例 db = Database() -
decision_manager.py 13.3 KB
#!/usr/bin/env python3 """ Agent 群聊协作系统 - 决策投票模块 负责决策提议的创建、投票、结果统计等 """ from datetime import datetime from typing import Optional, List, Dict, Any import sys import os sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) try: from database import db from agent_manager import AgentManager from message_manager import MessageManager except ImportError: from .database import db from .agent_manager import AgentManager from .message_manager import MessageManager class DecisionStatus: """决策状态常量""" PROPOSED = "proposed" DISCUSSING = "discussing" APPROVED = "approved" REJECTED = "rejected" IMPLEMENTED = "implemented" class VoteType: """投票类型常量""" FOR = "for" AGAINST = "against" ABSTAIN = "abstain" class Decision: """决策类""" def __init__(self, id: int = None, decision_db_id: int = None, decision_id: str = "", title: str = "", description: str = "", group_id: Optional[int] = None, proposer_id: int = None, status: str = "proposed", votes_for: int = 0, votes_against: int = 0, decided_at: Optional[str] = None, created_at: str = "", **kwargs): self.id = id if id is not None else decision_db_id self.decision_id = decision_id self.title = title self.description = description self.group_id = group_id self.proposer_id = proposer_id self.status = status self.votes_for = votes_for self.votes_against = votes_against self.decided_at = decided_at self.created_at = created_at # 额外字段 self.proposer_name: Optional[str] = kwargs.get('proposer_name') self.group_name: Optional[str] = kwargs.get('group_name') self.votes: List[Dict] = [] def to_dict(self) -> Dict[str, Any]: return { 'id': self.id, 'decision_id': self.decision_id, 'title': self.title, 'description': self.description, 'group_id': self.group_id, 'group_name': self.group_name, 'proposer_id': self.proposer_id, 'proposer_name': self.proposer_name, 'status': self.status, 'votes_for': self.votes_for, 'votes_against': self.votes_against, 'decided_at': self.decided_at, 'created_at': self.created_at, 'votes': self.votes } @property def total_votes(self) -> int: """获取总投票数""" return self.votes_for + self.votes_against @property def pass_rate(self) -> float: """获取通过率""" total = self.total_votes if total == 0: return 0.0 return (self.votes_for / total) * 100 def __repr__(self): return f"Decision({self.decision_id}: {self.title})" class DecisionManager: """决策管理器""" _decision_counter = 0 @staticmethod def generate_decision_id() -> str: """生成决策唯一标识""" DecisionManager._decision_counter += 1 return f"DEC-{datetime.now().strftime('%Y%m%d')}-{DecisionManager._decision_counter:03d}" @staticmethod def create(title: str, description: str, proposer_id: int, group_id: Optional[int] = None) -> Optional[Decision]: """创建决策提议""" decision_id = DecisionManager.generate_decision_id() try: db_id = db.insert( """INSERT INTO decisions (decision_id, title, description, group_id, proposer_id, status, votes_for, votes_against, created_at) VALUES (?, ?, ?, ?, ?, 'proposed', 0, 0, ?)""", (decision_id, title, description, group_id, proposer_id, datetime.now().isoformat()) ) # 发送决策提议消息 proposer = AgentManager.get_by_id(proposer_id) if proposer: content = f"📊 新决策提议\n\n**{title}**\n{description}\n\n请投票: for/against/abstain\n决策ID: {decision_id}" MessageManager.send_message( from_agent_id=proposer_id, content=content, group_id=group_id, msg_type="decision" ) return DecisionManager.get_by_id(db_id) except Exception as e: print(f"创建决策提议失败: {e}") return None @staticmethod def get_by_id(decision_db_id: int) -> Optional[Decision]: """通过 ID 获取决策""" row = db.fetch_one( """SELECT d.*, a.name as proposer_name, g.name as group_name FROM decisions d LEFT JOIN agents a ON d.proposer_id = a.id LEFT JOIN groups g ON d.group_id = g.id WHERE d.id = ?""", (decision_db_id,) ) if row: decision = Decision(**row) decision.proposer_name = row.get('proposer_name') decision.group_name = row.get('group_name') decision.votes = DecisionManager.get_votes(decision_db_id) return decision return None @staticmethod def get_by_decision_id(decision_id: str) -> Optional[Decision]: """通过决策标识获取决策""" row = db.fetch_one( """SELECT d.*, a.name as proposer_name, g.name as group_name FROM decisions d LEFT JOIN agents a ON d.proposer_id = a.id LEFT JOIN groups g ON d.group_id = g.id WHERE d.decision_id = ?""", (decision_id,) ) if row: decision = Decision(**row) decision.proposer_name = row.get('proposer_name') decision.group_name = row.get('group_name') decision.votes = DecisionManager.get_votes(row['id']) return decision return None @staticmethod def get_all(status: Optional[str] = None, group_id: Optional[int] = None) -> List[Decision]: """获取所有决策提议""" query = """SELECT d.*, a.name as proposer_name, g.name as group_name FROM decisions d LEFT JOIN agents a ON d.proposer_id = a.id LEFT JOIN groups g ON d.group_id = g.id""" params = [] conditions = [] if status: conditions.append("d.status = ?") params.append(status) if group_id: conditions.append("d.group_id = ?") params.append(group_id) if conditions: query += " WHERE " + " AND ".join(conditions) query += " ORDER BY d.created_at DESC" rows = db.fetch_all(query, tuple(params)) decisions = [] for row in rows: decision = Decision(**row) decision.proposer_name = row.get('proposer_name') decision.group_name = row.get('group_name') decision.votes = DecisionManager.get_votes(row['id']) decisions.append(decision) return decisions @staticmethod def vote(decision_db_id: int, agent_id: int, vote: str, comment: str = "") -> bool: """投票""" valid_votes = ['for', 'against', 'abstain'] if vote not in valid_votes: print(f"无效的投票选项: {vote}. 请使用 for/against/abstain") return False decision = DecisionManager.get_by_id(decision_db_id) if not decision: print("决策不存在") return False if decision.status not in ['proposed', 'discussing']: print(f"决策已关闭,无法投票 (当前状态: {decision.status})") return False # 检查是否已经投过票 existing = db.fetch_one( "SELECT id FROM decision_votes WHERE decision_id = ? AND agent_id = ?", (decision_db_id, agent_id) ) if existing: # 更新投票 db.execute( "UPDATE decision_votes SET vote = ?, comment = ? WHERE id = ?", (vote, comment, existing['id']) ) else: # 新增投票 db.execute( """INSERT INTO decision_votes (decision_id, agent_id, vote, comment, created_at) VALUES (?, ?, ?, ?, ?)""", (decision_db_id, agent_id, vote, comment, datetime.now().isoformat()) ) # 更新决策的投票计数 if vote == 'for': db.execute( "UPDATE decisions SET votes_for = votes_for + 1 WHERE id = ?", (decision_db_id,) ) elif vote == 'against': db.execute( "UPDATE decisions SET votes_against = votes_against + 1 WHERE id = ?", (decision_db_id,) ) # 发送投票通知 agent = AgentManager.get_by_id(agent_id) vote_text = {'for': '✅ 赞成', 'against': '❌ 反对', 'abstain': '⚪ 弃权'}.get(vote, vote) content = f"🗳️ {agent.name if agent else 'Agent'} 投票: {vote_text}\n决策: {decision.title}" if comment: content += f"\n意见: {comment}" MessageManager.send_message( from_agent_id=agent_id, content=content, group_id=decision.group_id, msg_type="chat" ) return True @staticmethod def update_status(decision_db_id: int, new_status: str, updater_id: int) -> bool: """更新决策状态""" valid_status = ['proposed', 'discussing', 'approved', 'rejected', 'implemented'] if new_status not in valid_status: print(f"无效的状态: {new_status}") return False decision = DecisionManager.get_by_id(decision_db_id) if not decision: return False decided_at = datetime.now().isoformat() if new_status in ['approved', 'rejected'] else None affected = db.execute( "UPDATE decisions SET status = ?, decided_at = ? WHERE id = ?", (new_status, decided_at, decision_db_id) ) if affected > 0: status_text = { 'proposed': '提议中', 'discussing': '讨论中', 'approved': '已通过', 'rejected': '已否决', 'implemented': '已实施' }.get(new_status, new_status) updater = AgentManager.get_by_id(updater_id) content = f"📊 决策状态更新\n\n**{decision.title}**\n新状态: {status_text}" MessageManager.send_message( from_agent_id=updater_id, content=content, group_id=decision.group_id, msg_type="decision" ) return True return False @staticmethod def get_votes(decision_db_id: int) -> List[Dict]: """获取决策的所有投票""" rows = db.fetch_all( """SELECT dv.*, a.name as agent_name FROM decision_votes dv JOIN agents a ON dv.agent_id = a.id WHERE dv.decision_id = ? ORDER BY dv.created_at""", (decision_db_id,) ) return [dict(row) for row in rows] @staticmethod def has_voted(decision_db_id: int, agent_id: int) -> bool: """检查 Agent 是否已经投票""" result = db.fetch_one( "SELECT 1 FROM decision_votes WHERE decision_id = ? AND agent_id = ?", (decision_db_id, agent_id) ) return result is not None @staticmethod def delete(decision_db_id: int) -> bool: """删除决策""" affected = db.execute("DELETE FROM decisions WHERE id = ?", (decision_db_id,)) return affected > 0 @staticmethod def format_decision_for_display(decision: Decision, show_votes: bool = False) -> str: """格式化决策用于显示""" status_emoji = { 'proposed': '📝', 'discussing': '💬', 'approved': '✅', 'rejected': '❌', 'implemented': '🚀' }.get(decision.status, '⚪') lines = [ f"{status_emoji} [{decision.decision_id}] {decision.title}", f" 提案人: {decision.proposer_name} | 状态: {decision.status}", f" 投票: ✅ {decision.votes_for} 票 | ❌ {decision.votes_against} 票 | 通过率: {decision.pass_rate:.1f}%" ] if decision.description: lines.append(f" 描述: {decision.description[:60]}{'...' if len(decision.description) > 60 else ''}") if show_votes and decision.votes: lines.append(" 投票详情:") for v in decision.votes: vote_emoji = {'for': '✅', 'against': '❌', 'abstain': '⚪'}.get(v['vote'], '⚪') lines.append(f" {vote_emoji} {v['agent_name']}: {v['vote']}") return "\n".join(lines) -
group_manager.py 8 KB
#!/usr/bin/env python3 """ Agent 群聊协作系统 - 群组管理模块 负责群组的创建、成员管理等 """ from datetime import datetime from typing import Optional, List, Dict, Any import sys import os sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) try: from database import db from agent_manager import AgentManager, Agent except ImportError: from .database import db from .agent_manager import AgentManager, Agent class Group: """群组类""" def __init__(self, id: int = None, group_id: int = None, name: str = "", description: str = "", owner_id: Optional[int] = None, created_at: str = "", **kwargs): self.id = id if id is not None else group_id self.name = name self.description = description self.owner_id = owner_id self.created_at = created_at # 额外字段 self.owner_name: Optional[str] = kwargs.get('owner_name') self.members: List[Agent] = [] def to_dict(self) -> Dict[str, Any]: return { 'id': self.id, 'name': self.name, 'description': self.description, 'owner_id': self.owner_id, 'owner_name': self.owner_name, 'created_at': self.created_at, 'member_count': len(self.members), 'members': [m.to_dict() for m in self.members] } def __repr__(self): return f"Group({self.name}, members={len(self.members)})" class GroupManager: """群组管理器""" @staticmethod def create(name: str, owner_id: int, description: str = "") -> Optional[Group]: """创建新群组""" try: group_id = db.insert( "INSERT INTO groups (name, description, owner_id, created_at) VALUES (?, ?, ?, ?)", (name, description, owner_id, datetime.now().isoformat()) ) # 自动将创建者加入群组 GroupManager.add_member(group_id, owner_id) return GroupManager.get_by_id(group_id) except Exception as e: print(f"创建群组失败: {e}") return None @staticmethod def get_by_id(group_id: int) -> Optional[Group]: """通过 ID 获取群组""" row = db.fetch_one( """SELECT g.*, a.name as owner_name FROM groups g LEFT JOIN agents a ON g.owner_id = a.id WHERE g.id = ?""", (group_id,) ) if row: group = Group(**row) group.owner_name = row.get('owner_name') group.members = GroupManager.get_members(group_id) return group return None @staticmethod def get_by_name(name: str) -> Optional[Group]: """通过名称获取群组""" row = db.fetch_one( """SELECT g.*, a.name as owner_name FROM groups g LEFT JOIN agents a ON g.owner_id = a.id WHERE g.name = ?""", (name,) ) if row: group = Group(**row) group.owner_name = row.get('owner_name') group.members = GroupManager.get_members(row['id']) return group return None @staticmethod def get_all() -> List[Group]: """获取所有群组""" rows = db.fetch_all( """SELECT g.*, a.name as owner_name FROM groups g LEFT JOIN agents a ON g.owner_id = a.id ORDER BY g.created_at DESC""" ) groups = [] for row in rows: group = Group(**row) group.owner_name = row.get('owner_name') group.members = GroupManager.get_members(row['id']) groups.append(group) return groups @staticmethod def get_agent_groups(agent_id: int) -> List[Group]: """获取 Agent 加入的所有群组""" rows = db.fetch_all( """SELECT g.*, a.name as owner_name FROM groups g JOIN group_members gm ON g.id = gm.group_id LEFT JOIN agents a ON g.owner_id = a.id WHERE gm.agent_id = ? ORDER BY g.created_at DESC""", (agent_id,) ) groups = [] for row in rows: group = Group(**row) group.owner_name = row.get('owner_name') group.members = GroupManager.get_members(row['id']) groups.append(group) return groups @staticmethod def add_member(group_id: int, agent_id: int) -> bool: """添加群组成员""" try: db.execute( "INSERT INTO group_members (group_id, agent_id, joined_at) VALUES (?, ?, ?)", (group_id, agent_id, datetime.now().isoformat()) ) return True except Exception as e: print(f"添加成员失败: {e}") return False @staticmethod def remove_member(group_id: int, agent_id: int) -> bool: """移除群组成员""" affected = db.execute( "DELETE FROM group_members WHERE group_id = ? AND agent_id = ?", (group_id, agent_id) ) return affected > 0 @staticmethod def get_members(group_id: int) -> List[Agent]: """获取群组成员列表""" rows = db.fetch_all( """SELECT a.* FROM agents a JOIN group_members gm ON a.id = gm.agent_id WHERE gm.group_id = ? ORDER BY gm.joined_at""", (group_id,) ) return [Agent(**row) for row in rows] @staticmethod def is_member(group_id: int, agent_id: int) -> bool: """检查 Agent 是否在群组中""" result = db.fetch_one( "SELECT 1 FROM group_members WHERE group_id = ? AND agent_id = ?", (group_id, agent_id) ) return result is not None @staticmethod def update(group_id: int, name: str = None, description: str = None) -> bool: """更新群组信息""" updates = [] params = [] if name: updates.append("name = ?") params.append(name) if description: updates.append("description = ?") params.append(description) if not updates: return False params.append(group_id) affected = db.execute( f"UPDATE groups SET {', '.join(updates)} WHERE id = ?", tuple(params) ) return affected > 0 @staticmethod def delete(group_id: int) -> bool: """删除群组(同时删除所有相关记录)""" # 数据库外键会处理相关记录的级联删除 affected = db.execute("DELETE FROM groups WHERE id = ?", (group_id,)) return affected > 0 @staticmethod def transfer_ownership(group_id: int, new_owner_id: int) -> bool: """转移群组所有权""" # 确保新群主在群组中 if not GroupManager.is_member(group_id, new_owner_id): GroupManager.add_member(group_id, new_owner_id) affected = db.execute( "UPDATE groups SET owner_id = ? WHERE id = ?", (new_owner_id, group_id) ) return affected > 0 @staticmethod def get_member_count(group_id: int) -> int: """获取群组成员数量""" result = db.fetch_one( "SELECT COUNT(*) as count FROM group_members WHERE group_id = ?", (group_id,) ) return result['count'] if result else 0 @staticmethod def list_online_members(group_id: int) -> List[Agent]: """获取群组在线成员""" rows = db.fetch_all( """SELECT a.* FROM agents a JOIN group_members gm ON a.id = gm.agent_id WHERE gm.group_id = ? AND a.status = 'online' ORDER BY a.last_active DESC""", (group_id,) ) return [Agent(**row) for row in rows] -
message_manager.py 11.7 KB
#!/usr/bin/env python3 """ Agent 群聊协作系统 - 消息核心模块 负责消息的创建、发送、@提及处理等 """ import re import json from datetime import datetime from typing import Optional, List, Dict, Any, Tuple from enum import Enum import sys import os sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) try: from database import db from agent_manager import AgentManager, Agent except ImportError: from .database import db from .agent_manager import AgentManager, Agent class MessageType(Enum): """消息类型枚举""" CHAT = "chat" # 普通聊天 MENTION = "mention" # @提及 TASK_ASSIGN = "task_assign" # 任务指派 TASK_COMPLETE = "task_complete" # 任务完成 DECISION = "decision" # 决策提议 SYSTEM = "system" # 系统消息 REPLY = "reply" # 回复消息 class Message: """消息类""" def __init__(self, id: int = None, msg_id: int = None, group_id: Optional[int] = None, from_agent_id: int = None, to_agent_id: Optional[int] = None, content: str = "", msg_type: str = "", type: str = "", reply_to: Optional[int] = None, created_at: str = "", **kwargs): self.id = id if id is not None else msg_id self.group_id = group_id self.from_agent_id = from_agent_id self.to_agent_id = to_agent_id self.content = content self.type = msg_type if msg_type else type self.reply_to = reply_to self.created_at = created_at # 额外字段(通过 JOIN 查询填充) self.from_agent_name: Optional[str] = kwargs.get('from_agent_name') self.to_agent_name: Optional[str] = kwargs.get('to_agent_name') self.group_name: Optional[str] = kwargs.get('group_name') def to_dict(self) -> Dict[str, Any]: return { 'id': self.id, 'group_id': self.group_id, 'group_name': self.group_name, 'from_agent_id': self.from_agent_id, 'from_agent_name': self.from_agent_name, 'to_agent_id': self.to_agent_id, 'to_agent_name': self.to_agent_name, 'content': self.content, 'type': self.type, 'reply_to': self.reply_to, 'created_at': self.created_at } def __repr__(self): return f"Message({self.id}: {self.from_agent_name} -> {self.to_agent_name or 'all'}: {self.content[:30]}...)" class MessageManager: """消息管理器""" # 用于匹配 @AgentName 的正则表达式 MENTION_PATTERN = re.compile(r'@([^\s@]+)') @staticmethod def send_message(from_agent_id: int, content: str, group_id: Optional[int] = None, to_agent_id: Optional[int] = None, msg_type: str = "chat", reply_to: Optional[int] = None) -> Optional[Message]: """发送消息""" # 检测消息中的 @提及 mentions = MessageManager.detect_mentions(content) # 如果消息包含 @提及且没有指定接收者,标记为 mention 类型 if mentions and msg_type == "chat": msg_type = "mention" # 插入消息 msg_id = db.insert( """INSERT INTO messages (group_id, from_agent_id, to_agent_id, content, type, reply_to, created_at) VALUES (?, ?, ?, ?, ?, ?, ?)""", (group_id, from_agent_id, to_agent_id, content, msg_type, reply_to, datetime.now().isoformat()) ) # 为 @提及的 Agent 创建收件箱通知 for mentioned_agent in mentions: MessageManager.create_inbox_notification(mentioned_agent.id, msg_id) # 如果是私信(指定了接收者),也为接收者创建通知 if to_agent_id: MessageManager.create_inbox_notification(to_agent_id, msg_id) return MessageManager.get_by_id(msg_id) @staticmethod def detect_mentions(content: str) -> List[Agent]: """检测消息中的 @提及""" mentioned_agents = [] matches = MessageManager.MENTION_PATTERN.findall(content) for name in matches: agent = AgentManager.get_by_name(name) if agent: mentioned_agents.append(agent) return mentioned_agents @staticmethod def create_inbox_notification(agent_id: int, message_id: int): """为 Agent 创建收件箱通知""" db.execute( "INSERT INTO agent_inbox (agent_id, message_id, is_read, notified_at) VALUES (?, ?, FALSE, ?)", (agent_id, message_id, datetime.now().isoformat()) ) @staticmethod def get_by_id(msg_id: int) -> Optional[Message]: """通过 ID 获取消息""" row = db.fetch_one( """SELECT m.*, fa.name as from_agent_name, ta.name as to_agent_name, g.name as group_name FROM messages m LEFT JOIN agents fa ON m.from_agent_id = fa.id LEFT JOIN agents ta ON m.to_agent_id = ta.id LEFT JOIN groups g ON m.group_id = g.id WHERE m.id = ?""", (msg_id,) ) if row: msg = Message(**row) return msg return None @staticmethod def get_group_messages(group_id: int, limit: int = 50, offset: int = 0) -> List[Message]: """获取群组消息历史""" rows = db.fetch_all( """SELECT m.*, fa.name as from_agent_name, ta.name as to_agent_name, g.name as group_name FROM messages m LEFT JOIN agents fa ON m.from_agent_id = fa.id LEFT JOIN agents ta ON m.to_agent_id = ta.id LEFT JOIN groups g ON m.group_id = g.id WHERE m.group_id = ? ORDER BY m.created_at DESC LIMIT ? OFFSET ?""", (group_id, limit, offset) ) return [MessageManager._row_to_message(row) for row in rows] @staticmethod def get_agent_inbox(agent_id: int, only_unread: bool = False) -> List[Dict[str, Any]]: """获取 Agent 的收件箱""" query = """SELECT ai.*, m.content, m.type, m.created_at as msg_created_at, fa.name as from_agent_name, g.name as group_name FROM agent_inbox ai JOIN messages m ON ai.message_id = m.id LEFT JOIN agents fa ON m.from_agent_id = fa.id LEFT JOIN groups g ON m.group_id = g.id WHERE ai.agent_id = ?""" if only_unread: query += " AND ai.is_read = FALSE" query += " ORDER BY m.created_at DESC" return db.fetch_all(query, (agent_id,)) @staticmethod def mark_as_read(agent_id: int, message_id: int) -> bool: """标记消息为已读""" affected = db.execute( "UPDATE agent_inbox SET is_read = TRUE, read_at = ? WHERE agent_id = ? AND message_id = ?", (datetime.now().isoformat(), agent_id, message_id) ) return affected > 0 @staticmethod def mark_all_as_read(agent_id: int) -> int: """标记所有消息为已读""" return db.execute( "UPDATE agent_inbox SET is_read = TRUE, read_at = ? WHERE agent_id = ? AND is_read = FALSE", (datetime.now().isoformat(), agent_id) ) @staticmethod def get_unread_count(agent_id: int) -> int: """获取未读消息数量""" result = db.fetch_one( "SELECT COUNT(*) as count FROM agent_inbox WHERE agent_id = ? AND is_read = FALSE", (agent_id,) ) return result['count'] if result else 0 @staticmethod def search_messages(keyword: str, group_id: Optional[int] = None, from_agent_id: Optional[int] = None) -> List[Message]: """搜索消息""" query = """SELECT m.*, fa.name as from_agent_name, ta.name as to_agent_name, g.name as group_name FROM messages m LEFT JOIN agents fa ON m.from_agent_id = fa.id LEFT JOIN agents ta ON m.to_agent_id = ta.id LEFT JOIN groups g ON m.group_id = g.id WHERE m.content LIKE ?""" params = [f"%{keyword}%"] if group_id: query += " AND m.group_id = ?" params.append(group_id) if from_agent_id: query += " AND m.from_agent_id = ?" params.append(from_agent_id) query += " ORDER BY m.created_at DESC LIMIT 100" rows = db.fetch_all(query, tuple(params)) return [MessageManager._row_to_message(row) for row in rows] @staticmethod def _row_to_message(row: Dict) -> Message: """将数据库行转换为 Message 对象""" msg = Message( msg_id=row['id'], group_id=row.get('group_id'), from_agent_id=row['from_agent_id'], to_agent_id=row.get('to_agent_id'), content=row['content'], msg_type=row['type'], reply_to=row.get('reply_to'), created_at=row['created_at'] ) msg.from_agent_name = row.get('from_agent_name') msg.to_agent_name = row.get('to_agent_name') msg.group_name = row.get('group_name') return msg @staticmethod def format_message_for_display(msg: Message) -> str: """格式化消息用于显示""" time_str = msg.created_at[11:19] if len(msg.created_at) > 19 else msg.created_at from_name = msg.from_agent_name or f"Agent-{msg.from_agent_id}" if msg.group_name: location = f"[{msg.group_name}]" else: location = "[私信]" if msg.to_agent_name: target = f" @{msg.to_agent_name}" else: target = "" return f"[{time_str}] {location} {from_name}{target}: {msg.content}" class MessageFormatter: """消息格式化工具""" @staticmethod def chat(content: str) -> str: """普通聊天消息""" return content @staticmethod def mention(content: str, agent_names: List[str]) -> str: """@提及消息""" mentions = " ".join([f"@{name}" for name in agent_names]) return f"{mentions} {content}" @staticmethod def task_assign(assignee: str, task_title: str, description: str = "", priority: str = "normal", due_date: str = "") -> str: """任务指派消息""" lines = [f"@{assignee} 新任务指派", f"标题: {task_title}"] if description: lines.append(f"描述: {description}") lines.append(f"优先级: {priority}") if due_date: lines.append(f"截止日期: {due_date}") return "\n".join(lines) @staticmethod def task_complete(task_id: str, result: str = "") -> str: """任务完成消息""" lines = [f"任务 {task_id} 已完成"] if result: lines.append(f"结果: {result}") return "\n".join(lines) @staticmethod def decision_proposal(title: str, description: str, options: List[str] = None) -> str: """决策提议消息""" lines = [f"【决策提议】{title}", f"描述: {description}"] if options: lines.append("选项:") for i, opt in enumerate(options, 1): lines.append(f" {i}. {opt}") return "\n".join(lines) -
task_manager.py 12.8 KB
#!/usr/bin/env python3 """ Agent 群聊协作系统 - 任务管理模块 负责任务的创建、指派、状态更新、评论等 """ from datetime import datetime from typing import Optional, List, Dict, Any import sys import os sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) try: from database import db from agent_manager import AgentManager from message_manager import MessageManager except ImportError: from .database import db from .agent_manager import AgentManager from .message_manager import MessageManager class TaskStatus: """任务状态常量""" PENDING = "pending" IN_PROGRESS = "in_progress" COMPLETED = "completed" CANCELLED = "cancelled" class TaskPriority: """任务优先级常量""" LOW = "low" NORMAL = "normal" HIGH = "high" URGENT = "urgent" class Task: """任务类""" def __init__(self, id: int = None, task_db_id: int = None, task_id: str = "", title: str = "", description: str = "", assigner_id: int = None, assignee_id: int = None, group_id: Optional[int] = None, status: str = "pending", priority: str = "normal", due_date: Optional[str] = None, completed_at: Optional[str] = None, created_at: str = "", **kwargs): self.id = id if id is not None else task_db_id self.task_id = task_id self.title = title self.description = description self.assigner_id = assigner_id self.assignee_id = assignee_id self.group_id = group_id self.status = status self.priority = priority self.due_date = due_date self.completed_at = completed_at self.created_at = created_at # 额外字段 self.assigner_name: Optional[str] = kwargs.get('assigner_name') self.assignee_name: Optional[str] = kwargs.get('assignee_name') self.group_name: Optional[str] = kwargs.get('group_name') self.comments: List[Dict] = [] def to_dict(self) -> Dict[str, Any]: return { 'id': self.id, 'task_id': self.task_id, 'title': self.title, 'description': self.description, 'assigner_id': self.assigner_id, 'assigner_name': self.assigner_name, 'assignee_id': self.assignee_id, 'assignee_name': self.assignee_name, 'group_id': self.group_id, 'group_name': self.group_name, 'status': self.status, 'priority': self.priority, 'due_date': self.due_date, 'completed_at': self.completed_at, 'created_at': self.created_at, 'comments': self.comments } def __repr__(self): return f"Task({self.task_id}: {self.title} -> {self.assignee_name})" class TaskManager: """任务管理器""" _task_counter = 0 @staticmethod def generate_task_id() -> str: """生成任务唯一标识""" TaskManager._task_counter += 1 return f"TASK-{datetime.now().strftime('%Y%m%d')}-{TaskManager._task_counter:03d}" @staticmethod def create(title: str, assigner_id: int, assignee_id: int, description: str = "", group_id: Optional[int] = None, priority: str = "normal", due_date: Optional[str] = None) -> Optional[Task]: """创建新任务""" task_id = TaskManager.generate_task_id() try: db_id = db.insert( """INSERT INTO tasks (task_id, title, description, assigner_id, assignee_id, group_id, status, priority, due_date, created_at) VALUES (?, ?, ?, ?, ?, ?, 'pending', ?, ?, ?)""", (task_id, title, description, assigner_id, assignee_id, group_id, priority, due_date, datetime.now().isoformat()) ) # 发送任务指派消息 assigner = AgentManager.get_by_id(assigner_id) assignee = AgentManager.get_by_id(assignee_id) if assigner and assignee: content = f"📝 新任务指派给 @{assignee.name}\n\n**{title}**\n{description}\n\n优先级: {priority}" if due_date: content += f" | 截止: {due_date}" content += f" | 任务ID: {task_id}" MessageManager.send_message( from_agent_id=assigner_id, content=content, group_id=group_id, to_agent_id=assignee_id, msg_type="task_assign" ) return TaskManager.get_by_id(db_id) except Exception as e: print(f"创建任务失败: {e}") return None @staticmethod def get_by_id(task_db_id: int) -> Optional[Task]: """通过 ID 获取任务""" row = db.fetch_one( """SELECT t.*, a1.name as assigner_name, a2.name as assignee_name, g.name as group_name FROM tasks t LEFT JOIN agents a1 ON t.assigner_id = a1.id LEFT JOIN agents a2 ON t.assignee_id = a2.id LEFT JOIN groups g ON t.group_id = g.id WHERE t.id = ?""", (task_db_id,) ) if row: task = Task(**row) task.assigner_name = row.get('assigner_name') task.assignee_name = row.get('assignee_name') task.group_name = row.get('group_name') task.comments = TaskManager.get_comments(task_db_id) return task return None @staticmethod def get_by_task_id(task_id: str) -> Optional[Task]: """通过任务标识获取任务""" row = db.fetch_one( """SELECT t.*, a1.name as assigner_name, a2.name as assignee_name, g.name as group_name FROM tasks t LEFT JOIN agents a1 ON t.assigner_id = a1.id LEFT JOIN agents a2 ON t.assignee_id = a2.id LEFT JOIN groups g ON t.group_id = g.id WHERE t.task_id = ?""", (task_id,) ) if row: task = Task(**row) task.assigner_name = row.get('assigner_name') task.assignee_name = row.get('assignee_name') task.group_name = row.get('group_name') task.comments = TaskManager.get_comments(row['id']) return task return None @staticmethod def get_all(status: Optional[str] = None, assignee_id: Optional[int] = None) -> List[Task]: """获取所有任务""" query = """SELECT t.*, a1.name as assigner_name, a2.name as assignee_name, g.name as group_name FROM tasks t LEFT JOIN agents a1 ON t.assigner_id = a1.id LEFT JOIN agents a2 ON t.assignee_id = a2.id LEFT JOIN groups g ON t.group_id = g.id""" params = [] conditions = [] if status: conditions.append("t.status = ?") params.append(status) if assignee_id: conditions.append("t.assignee_id = ?") params.append(assignee_id) if conditions: query += " WHERE " + " AND ".join(conditions) query += " ORDER BY t.created_at DESC" rows = db.fetch_all(query, tuple(params)) tasks = [] for row in rows: task = Task(**row) task.assigner_name = row.get('assigner_name') task.assignee_name = row.get('assignee_name') task.group_name = row.get('group_name') task.comments = TaskManager.get_comments(row['id']) tasks.append(task) return tasks @staticmethod def update_status(task_db_id: int, new_status: str, updater_id: int, comment: str = "") -> bool: """更新任务状态""" valid_status = ['pending', 'in_progress', 'completed', 'cancelled'] if new_status not in valid_status: print(f"无效的状态: {new_status}") return False task = TaskManager.get_by_id(task_db_id) if not task: return False completed_at = datetime.now().isoformat() if new_status == 'completed' else None affected = db.execute( "UPDATE tasks SET status = ?, completed_at = ? WHERE id = ?", (new_status, completed_at, task_db_id) ) if affected > 0: # 添加评论记录状态变更 status_text = { 'pending': '待处理', 'in_progress': '进行中', 'completed': '已完成', 'cancelled': '已取消' }.get(new_status, new_status) updater = AgentManager.get_by_id(updater_id) updater_name = updater.name if updater else f"Agent-{updater_id}" comment_text = f"状态变更为: {status_text}" if comment: comment_text += f" | 备注: {comment}" TaskManager.add_comment(task_db_id, updater_id, comment_text) # 发送状态变更通知 content = f"✅ 任务 {task.task_id} 状态更新\n\n**{task.title}**\n新状态: {status_text}" if comment: content += f"\n备注: {comment}" MessageManager.send_message( from_agent_id=updater_id, content=content, group_id=task.group_id, to_agent_id=task.assignee_id if updater_id != task.assignee_id else task.assigner_id, msg_type="task_complete" if new_status == 'completed' else "chat" ) return True return False @staticmethod def start_task(task_db_id: int, agent_id: int) -> bool: """开始任务(状态变为 in_progress)""" return TaskManager.update_status(task_db_id, 'in_progress', agent_id, "开始处理任务") @staticmethod def complete_task(task_db_id: int, agent_id: int, result: str = "") -> bool: """完成任务""" return TaskManager.update_status(task_db_id, 'completed', agent_id, result) @staticmethod def add_comment(task_db_id: int, agent_id: int, comment: str) -> bool: """添加任务评论""" try: db.execute( "INSERT INTO task_comments (task_id, agent_id, comment, created_at) VALUES (?, ?, ?, ?)", (task_db_id, agent_id, comment, datetime.now().isoformat()) ) return True except Exception as e: print(f"添加评论失败: {e}") return False @staticmethod def get_comments(task_db_id: int) -> List[Dict]: """获取任务评论""" rows = db.fetch_all( """SELECT tc.*, a.name as agent_name FROM task_comments tc JOIN agents a ON tc.agent_id = a.id WHERE tc.task_id = ? ORDER BY tc.created_at""", (task_db_id,) ) return [dict(row) for row in rows] @staticmethod def delete(task_db_id: int) -> bool: """删除任务""" affected = db.execute("DELETE FROM tasks WHERE id = ?", (task_db_id,)) return affected > 0 @staticmethod def get_agent_tasks(agent_id: int, status: Optional[str] = None) -> List[Task]: """获取指定 Agent 的任务列表""" return TaskManager.get_all(status=status, assignee_id=agent_id) @staticmethod def format_task_for_display(task: Task) -> str: """格式化任务用于显示""" priority_emoji = { 'low': '🔵', 'normal': '🟡', 'high': '🟠', 'urgent': '🔴' }.get(task.priority, '⚪') status_emoji = { 'pending': '⏳', 'in_progress': '🔄', 'completed': '✅', 'cancelled': '❌' }.get(task.status, '⚪') lines = [ f"{status_emoji} {priority_emoji} [{task.task_id}] {task.title}", f" 指派给: {task.assignee_name} | 来自: {task.assigner_name}", ] if task.description: lines.append(f" 描述: {task.description[:50]}{'...' if len(task.description) > 50 else ''}") if task.due_date: lines.append(f" 截止: {task.due_date}") if task.comments: lines.append(f" 💬 {len(task.comments)} 条评论") return "\n".join(lines) -
__init__.py 1.9 KB
""" Agent Network - Multi-Agent Group Chat Collaboration System A complete multi-agent collaboration platform with group chat, @mentions, task management, and decision voting. Example: >>> from agent_network import AgentManager, GroupManager, init_default_agents >>> from agent_network import get_coordinator >>> >>> # Initialize >>> init_default_agents() >>> >>> # Use coordinator >>> coord = get_coordinator() >>> coord.register_agent(1) >>> coord.send_message(1, "Hello team!", group_id=1) """ __version__ = "1.0.0" __author__ = "Agent Network Team" # Core imports from .database import Database, db from .agent_manager import Agent, AgentManager, init_default_agents from .group_manager import Group, GroupManager from .message_manager import Message, MessageManager, MessageType, MessageFormatter from .task_manager import Task, TaskManager from .decision_manager import Decision, DecisionManager from .coordinator import Coordinator, get_coordinator, AgentSession __all__ = [ # Version "__version__", # Database "Database", "db", # Agent "Agent", "AgentManager", "init_default_agents", # Group "Group", "GroupManager", # Message "Message", "MessageManager", "MessageType", "MessageFormatter", # Task "Task", "TaskManager", # Decision "Decision", "DecisionManager", # Coordinator "Coordinator", "get_coordinator", "AgentSession", ] # Constants DEFAULT_AGENTS = [ ("老邢", "Manager", "Overall coordination and decision making"), ("小邢", "DevOps", "Development and operations"), ("小金", "Finance Analyst", "Financial market analysis"), ("小陈", "Trader", "Trading execution"), ("小影", "Designer", "Design and short video content"), ("小视频", "Video Producer", "Video production and editing"), ]
-
-
cli.py 20.5 KB
#!/usr/bin/env python3 """ Agent 群聊协作系统 - 交互式 CLI 界面 提供类似钉钉/飞书的群聊交互体验 """ import os import sys import time import readline from typing import Optional, List from datetime import datetime # 添加 src 到路径 sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) from src.database import db from src.agent_manager import AgentManager, Agent, init_default_agents from src.group_manager import GroupManager, Group from src.message_manager import MessageManager, Message, MessageFormatter from src.task_manager import TaskManager, Task from src.decision_manager import DecisionManager, Decision class Colors: """终端颜色""" RESET = '\033[0m' BOLD = '\033[1m' DIM = '\033[2m' RED = '\033[91m' GREEN = '\033[92m' YELLOW = '\033[93m' BLUE = '\033[94m' MAGENTA = '\033[95m' CYAN = '\033[96m' WHITE = '\033[97m' class AgentChatCLI: """Agent 群聊 CLI 界面""" def __init__(self): self.current_agent: Optional[Agent] = None self.current_group: Optional[Group] = None self.running = True def clear_screen(self): """清屏""" os.system('clear' if os.name == 'posix' else 'cls') def print_header(self, title: str): """打印标题""" print(f"\n{Colors.CYAN}{'='*60}{Colors.RESET}") print(f"{Colors.BOLD}{Colors.WHITE}{title.center(60)}{Colors.RESET}") print(f"{Colors.CYAN}{'='*60}{Colors.RESET}\n") def print_success(self, message: str): """打印成功消息""" print(f"{Colors.GREEN}✓ {message}{Colors.RESET}") def print_error(self, message: str): """打印错误消息""" print(f"{Colors.RED}✗ {message}{Colors.RESET}") def print_info(self, message: str): """打印信息""" print(f"{Colors.BLUE}ℹ {message}{Colors.RESET}") def print_warning(self, message: str): """打印警告""" print(f"{Colors.YELLOW}⚠ {message}{Colors.RESET}") def get_input(self, prompt: str) -> str: """获取用户输入""" try: return input(f"{Colors.CYAN}{prompt}{Colors.RESET}").strip() except EOFError: return "" def login_menu(self): """登录菜单""" self.clear_screen() self.print_header("🤖 Agent Network - 群聊协作系统") print(f"{Colors.DIM}初始化默认 Agent...{Colors.RESET}") init_default_agents() agents = AgentManager.get_all() print(f"\n{Colors.BOLD}可用 Agent 列表:{Colors.RESET}\n") for i, agent in enumerate(agents, 1): status_color = Colors.GREEN if agent.status == 'online' else Colors.DIM print(f" {Colors.YELLOW}[{i}]{Colors.RESET} {status_color}{agent.name}{Colors.RESET} - {agent.role}") print(f"\n {Colors.YELLOW}[0]{Colors.RESET} 退出系统") choice = self.get_input("\n请选择 Agent (输入编号): ") if choice == '0': self.running = False return try: idx = int(choice) - 1 if 0 <= idx < len(agents): self.current_agent = agents[idx] AgentManager.go_online(self.current_agent.id) self.current_agent.status = 'online' self.print_success(f"欢迎, {self.current_agent.name}!") time.sleep(1) else: self.print_error("无效的选择") time.sleep(1) except ValueError: self.print_error("请输入有效的数字") time.sleep(1) def main_menu(self): """主菜单""" while self.running and self.current_agent: self.clear_screen() # 获取未读消息数 unread_count = MessageManager.get_unread_count(self.current_agent.id) unread_badge = f" [{Colors.RED}{unread_count} 未读{Colors.RESET}]" if unread_count > 0 else "" group_name = f" @{self.current_group.name}" if self.current_group else "" self.print_header(f"🤖 {self.current_agent.name}{group_name}{unread_badge}") print(f"{Colors.BOLD}主菜单:{Colors.RESET}\n") print(f" {Colors.YELLOW}[1]{Colors.RESET} 进入群组") print(f" {Colors.YELLOW}[2]{Colors.RESET} 创建群组") print(f" {Colors.YELLOW}[3]{Colors.RESET} 查看任务") print(f" {Colors.YELLOW}[4]{Colors.RESET} 查看决策") print(f" {Colors.YELLOW}[5]{Colors.RESET} 查看收件箱{unread_badge}") print(f" {Colors.YELLOW}[6]{Colors.RESET} 切换 Agent") print(f" {Colors.YELLOW}[0]{Colors.RESET} 退出") choice = self.get_input("\n请选择操作: ") if choice == '1': self.select_group() elif choice == '2': self.create_group() elif choice == '3': self.view_tasks() elif choice == '4': self.view_decisions() elif choice == '5': self.view_inbox() elif choice == '6': AgentManager.go_offline(self.current_agent.id) self.current_agent = None self.current_group = None return elif choice == '0': self.logout() else: self.print_error("无效的选择") time.sleep(1) def select_group(self): """选择群组""" groups = GroupManager.get_agent_groups(self.current_agent.id) if not groups: self.print_warning("你还没有加入任何群组") self.get_input("按回车继续...") return self.clear_screen() self.print_header("📁 选择群组") print(f"{Colors.BOLD}你的群组:{Colors.RESET}\n") for i, group in enumerate(groups, 1): member_count = len(group.members) online_count = len([m for m in group.members if m.status == 'online']) print(f" {Colors.YELLOW}[{i}]{Colors.RESET} {group.name} ({online_count}/{member_count} 在线)") if group.description: print(f" {Colors.DIM}{group.description}{Colors.RESET}") print(f"\n {Colors.YELLOW}[0]{Colors.RESET} 返回") choice = self.get_input("\n请选择群组: ") if choice == '0': return try: idx = int(choice) - 1 if 0 <= idx < len(groups): self.current_group = groups[idx] self.enter_group_chat() else: self.print_error("无效的选择") time.sleep(1) except ValueError: self.print_error("请输入有效的数字") time.sleep(1) def enter_group_chat(self): """进入群组聊天""" if not self.current_group: return while self.running: self.clear_screen() # 获取在线成员 online_members = GroupManager.list_online_members(self.current_group.id) online_names = [m.name for m in online_members] header = f"💬 {self.current_group.name} ({len(online_members)} 人在线)" self.print_header(header) # 显示最近消息 messages = MessageManager.get_group_messages(self.current_group.id, limit=20) messages.reverse() # 按时间正序显示 if messages: for msg in messages: self.display_message(msg) else: print(f"{Colors.DIM}暂无消息,开始聊天吧!{Colors.RESET}") print(f"\n{Colors.CYAN}{'-'*60}{Colors.RESET}") print(f"{Colors.DIM}在线: {', '.join(online_names) or '无'}{Colors.RESET}") print(f"{Colors.CYAN}{'-'*60}{Colors.RESET}") print(f"\n{Colors.BOLD}命令:{Colors.RESET} @Agent名 提及 | /task 任务 | /decision 决策 | /quit 退出") content = self.get_input(f"{self.current_agent.name}: ") if not content: continue if content == '/quit': # 发送离开消息 MessageManager.send_message( from_agent_id=self.current_agent.id, content=f"{self.current_agent.name} 离开了群组", group_id=self.current_group.id, msg_type="system" ) self.current_group = None return elif content == '/task': self.create_task_in_chat() elif content == '/decision': self.create_decision_in_chat() elif content.startswith('/'): self.handle_command(content) else: # 发送消息 MessageManager.send_message( from_agent_id=self.current_agent.id, content=content, group_id=self.current_group.id ) def display_message(self, msg: Message): """显示消息""" time_str = msg.created_at[11:16] if len(msg.created_at) > 16 else msg.created_at from_name = msg.from_agent_name or f"Agent-{msg.from_agent_id}" # 根据消息类型使用不同颜色 if msg.type == 'system': print(f"{Colors.DIM}[{time_str}] {msg.content}{Colors.RESET}") elif msg.type == 'task_assign': print(f"{Colors.YELLOW}[{time_str}] {from_name}:{Colors.RESET}") print(f"{Colors.YELLOW} 📝 {msg.content}{Colors.RESET}") elif msg.type == 'decision': print(f"{Colors.MAGENTA}[{time_str}] {from_name}:{Colors.RESET}") print(f"{Colors.MAGENTA} 📊 {msg.content}{Colors.RESET}") else: # 普通消息 if msg.to_agent_name: print(f"{Colors.GREEN}[{time_str}] {from_name} -> @{msg.to_agent_name}:{Colors.RESET}") else: print(f"{Colors.GREEN}[{time_str}] {from_name}:{Colors.RESET}") print(f" {msg.content}") def handle_command(self, cmd: str): """处理命令""" parts = cmd.split() command = parts[0].lower() if command == '/help': self.show_help() elif command == '/members': self.show_members() elif command == '/tasks': self.show_group_tasks() elif command == '/online': self.show_online_status() else: self.print_error(f"未知命令: {command}") time.sleep(1) def show_help(self): """显示帮助""" self.clear_screen() self.print_header("📖 命令帮助") commands = [ ("/quit", "退出当前群组"), ("/task", "创建任务"), ("/decision", "创建决策投票"), ("/members", "查看群组成员"), ("/tasks", "查看群组任务"), ("/online", "查看在线状态"), ("/help", "显示此帮助"), ("@Agent名", "提及/私信某个 Agent"), ] for cmd, desc in commands: print(f" {Colors.CYAN}{cmd.ljust(15)}{Colors.RESET} {desc}") self.get_input("\n按回车继续...") def show_members(self): """显示群组成员""" if not self.current_group: return members = GroupManager.get_members(self.current_group.id) self.clear_screen() self.print_header(f"👥 {self.current_group.name} - 成员列表") for member in members: status_emoji = "🟢" if member.status == 'online' else "⚪" print(f" {status_emoji} {Colors.BOLD}{member.name}{Colors.RESET} - {member.role}") if member.description: print(f" {Colors.DIM}{member.description}{Colors.RESET}") self.get_input("\n按回车继续...") def create_group(self): """创建群组""" self.clear_screen() self.print_header("📁 创建新群组") name = self.get_input("群组名称: ") if not name: self.print_error("群组名称不能为空") time.sleep(1) return description = self.get_input("群组描述 (可选): ") group = GroupManager.create(name, self.current_agent.id, description) if group: self.print_success(f"群组 '{name}' 创建成功!") # 发送系统消息 MessageManager.send_message( from_agent_id=self.current_agent.id, content=f"📁 群组 '{name}' 已创建", group_id=group.id, msg_type="system" ) else: self.print_error("创建群组失败") time.sleep(1) def create_task_in_chat(self): """在聊天中创建任务""" if not self.current_group: return self.clear_screen() self.print_header("📝 创建任务") title = self.get_input("任务标题: ") if not title: self.print_error("任务标题不能为空") time.sleep(1) return description = self.get_input("任务描述: ") # 选择指派人 members = GroupManager.get_members(self.current_group.id) print(f"\n{Colors.BOLD}选择指派人:{Colors.RESET}") for i, member in enumerate(members, 1): print(f" {Colors.YELLOW}[{i}]{Colors.RESET} {member.name}") choice = self.get_input("选择指派人 (编号): ") try: idx = int(choice) - 1 if 0 <= idx < len(members): assignee = members[idx] priority = self.get_input("优先级 (low/normal/high/urgent) [normal]: ") or "normal" due_date = self.get_input("截止日期 (YYYY-MM-DD, 可选): ") task = TaskManager.create( title=title, assigner_id=self.current_agent.id, assignee_id=assignee.id, description=description, group_id=self.current_group.id, priority=priority, due_date=due_date if due_date else None ) if task: self.print_success(f"任务 '{title}' 已指派给 {assignee.name}") else: self.print_error("创建任务失败") else: self.print_error("无效的选择") except ValueError: self.print_error("请输入有效的数字") time.sleep(1) def create_decision_in_chat(self): """在聊天中创建决策""" if not self.current_group: return self.clear_screen() self.print_header("📊 创建决策投票") title = self.get_input("决策标题: ") if not title: self.print_error("决策标题不能为空") time.sleep(1) return description = self.get_input("决策描述: ") decision = DecisionManager.create( title=title, description=description, proposer_id=self.current_agent.id, group_id=self.current_group.id ) if decision: self.print_success(f"决策 '{title}' 已创建,等待投票") else: self.print_error("创建决策失败") time.sleep(1) def view_tasks(self): """查看任务""" self.clear_screen() self.print_header("📝 任务列表") tasks = TaskManager.get_all() my_tasks = TaskManager.get_agent_tasks(self.current_agent.id) if not tasks: print(f"{Colors.DIM}暂无任务{Colors.RESET}") else: print(f"\n{Colors.BOLD}我的任务:{Colors.RESET}\n") for task in my_tasks: print(TaskManager.format_task_for_display(task)) print() print(f"\n{Colors.BOLD}所有任务:{Colors.RESET}\n") for task in tasks[:10]: # 显示最近10个 print(TaskManager.format_task_for_display(task)) print() self.get_input("\n按回车继续...") def view_decisions(self): """查看决策""" self.clear_screen() self.print_header("📊 决策列表") decisions = DecisionManager.get_all() if not decisions: print(f"{Colors.DIM}暂无决策提议{Colors.RESET}") else: for decision in decisions[:10]: print(DecisionManager.format_decision_for_display(decision, show_votes=True)) print() self.get_input("\n按回车继续...") def view_inbox(self): """查看收件箱""" self.clear_screen() self.print_header("📥 收件箱") inbox = MessageManager.get_agent_inbox(self.current_agent.id) if not inbox: print(f"{Colors.DIM}收件箱为空{Colors.RESET}") else: for item in inbox[:20]: read_status = "✓" if item['is_read'] else "●" status_color = Colors.DIM if item['is_read'] else Colors.GREEN time_str = item['msg_created_at'][11:16] if len(item['msg_created_at']) > 16 else item['msg_created_at'] from_name = item['from_agent_name'] or "系统" group_info = f"[{item['group_name']}] " if item['group_name'] else "" content_preview = item['content'][:40] + "..." if len(item['content']) > 40 else item['content'] print(f"{status_color}{read_status} [{time_str}] {group_info}{from_name}: {content_preview}{Colors.RESET}") # 标记所有为已读 MessageManager.mark_all_as_read(self.current_agent.id) unread_count = MessageManager.get_unread_count(self.current_agent.id) if unread_count == 0: self.print_success("所有消息已标记为已读") self.get_input("\n按回车继续...") def show_online_status(self): """显示在线状态""" agents = AgentManager.get_all() self.clear_screen() self.print_header("🟢 在线状态") for agent in agents: status_emoji = "🟢" if agent.status == 'online' else "⚪" status_text = agent.status.upper() print(f" {status_emoji} {Colors.BOLD}{agent.name}{Colors.RESET} - {status_text}") self.get_input("\n按回车继续...") def show_group_tasks(self): """显示群组任务""" if not self.current_group: return tasks = TaskManager.get_all() group_tasks = [t for t in tasks if t.group_id == self.current_group.id] self.clear_screen() self.print_header(f"📝 {self.current_group.name} - 任务列表") if not group_tasks: print(f"{Colors.DIM}暂无任务{Colors.RESET}") else: for task in group_tasks: print(TaskManager.format_task_for_display(task)) print() self.get_input("\n按回车继续...") def logout(self): """退出登录""" if self.current_agent: AgentManager.go_offline(self.current_agent.id) self.print_info(f"再见, {self.current_agent.name}!") self.running = False def run(self): """运行 CLI""" while self.running: if not self.current_agent: self.login_menu() else: self.main_menu() self.clear_screen() self.print_header("感谢使用 Agent Network!") def main(): """主函数""" cli = AgentChatCLI() try: cli.run() except KeyboardInterrupt: print(f"\n\n{Colors.YELLOW}程序被中断{Colors.RESET}") if cli.current_agent: AgentManager.go_offline(cli.current_agent.id) if __name__ == "__main__": main() -
demo.py 13 KB
#!/usr/bin/env python3 """ Agent 群聊协作系统 - 完整演示脚本 展示所有核心功能 """ import os import sys import time # 添加 src 目录到路径 sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src')) from agent_manager import AgentManager, init_default_agents from message_manager import MessageManager from group_manager import GroupManager from task_manager import TaskManager, TaskStatus from decision_manager import DecisionManager, DecisionStatus, VoteType from coordinator import get_coordinator def print_header(title): """打印标题""" print("\n" + "=" * 70) print(f" {title}") print("=" * 70) def print_section(title): """打印小节标题""" print(f"\n▶ {title}") print("-" * 50) def demo(): """运行演示""" print_header("🤖 Agent 群聊协作系统 v1.0 - 功能演示") print(""" 本演示将展示系统的核心功能: 1️⃣ Agent 管理与上线 2️⃣ 群组创建与加入 3️⃣ 消息发送与 @提及 4️⃣ 任务指派与跟踪 5️⃣ 决策提议与投票 6️⃣ 收件箱与通知 """) input("\n按 Enter 开始演示...") # 初始化 init_default_agents() coordinator = get_coordinator() coordinator.start() time.sleep(0.5) # ========== 1. Agent 管理 ========== print_header("1️⃣ Agent 管理") print_section("所有 Agent 列表") agents = AgentManager.get_all() for agent in agents: print(f" ⚪ {agent.name} - {agent.role}") print_section("Agent 上线") lao_xing = AgentManager.get_by_name("老邢") xiao_xing = AgentManager.get_by_name("小邢") xiao_jin = AgentManager.get_by_name("小金") xiao_chen = AgentManager.get_by_name("小陈") xiao_ying = AgentManager.get_by_name("小影") for agent in [lao_xing, xiao_xing, xiao_jin, xiao_chen, xiao_ying]: if agent: coordinator.register_agent(agent.id) time.sleep(0.2) print_section("在线 Agent 列表") online = AgentManager.get_online_agents() for agent in online: print(f" 🟢 {agent.name} - {agent.role}") time.sleep(1) # ========== 2. 群组管理 ========== print_header("2️⃣ 群组管理") print_section("创建工作群组") if lao_xing: group = GroupManager.create("核心工作群", lao_xing.id, "核心团队工作沟通") if group: print(f" ✅ 群组 '{group.name}' 创建成功") # 添加成员 for agent in [xiao_xing, xiao_jin, xiao_chen, xiao_ying]: if agent: GroupManager.add_member(group.id, agent.id) print(f" ✅ {agent.name} 加入群组") else: group = GroupManager.get_by_name("核心工作群") print_section("群组列表") groups = GroupManager.get_all() for g in groups: member_count = GroupManager.get_member_count(g.id) print(f" 📁 {g.name} - {member_count} 成员") print_section("群组成员") if group: members = GroupManager.get_members(group.id) print(f" '{group.name}' 成员:") for member in members: status = "🟢" if member.status == "online" else "⚪" print(f" {status} {member.name} ({member.role})") time.sleep(1) # ========== 3. 消息功能 ========== print_header("3️⃣ 消息功能") print_section("发送普通消息") if lao_xing and group: msg1 = coordinator.send_message( from_agent_id=lao_xing.id, content="大家好!今天我们来讨论一下本周的工作安排。", group_id=group.id ) if msg1: print(f" 💬 老邢: {msg1.content}") time.sleep(0.5) print_section("@提及功能") if lao_xing and group: msg2 = coordinator.send_message( from_agent_id=lao_xing.id, content="@小邢 请汇报一下服务器状态,@小金 准备一下市场分析报告。", group_id=group.id ) if msg2: print(f" 💬 老邢: {msg2.content}") print(f" 📢 检测到 @提及,已通知相关 Agent") time.sleep(0.5) print_section("群聊回复") if xiao_xing and group: msg3 = coordinator.send_message( from_agent_id=xiao_xing.id, content="@老邢 服务器运行正常,负载在20%左右,一切稳定。", group_id=group.id ) if msg3: print(f" 💬 小邢: {msg3.content}") if xiao_jin and group: msg4 = coordinator.send_message( from_agent_id=xiao_jin.id, content="@老邢 市场分析正在整理中,预计下午完成。", group_id=group.id ) if msg4: print(f" 💬 小金: {msg4.content}") time.sleep(1) # ========== 4. 任务管理 ========== print_header("4️⃣ 任务管理") print_section("指派任务") tasks_created = [] if lao_xing and xiao_jin and group: task1 = coordinator.assign_task( title="撰写市场分析报告", description="分析本周美股市场走势,重点关注科技股板块", assigner_id=lao_xing.id, assignee_id=xiao_jin.id, group_id=group.id, priority="high" ) if task1: print(f" ✅ 任务创建: {task1['task_id']}") print(f" 标题: {task1['title']}") print(f" 指派给: {task1['assignee_name']}") print(f" 优先级: {task1['priority']}") tasks_created.append(task1) time.sleep(0.3) if lao_xing and xiao_xing and group: task2 = coordinator.assign_task( title="系统安全扫描", description="对生产环境进行安全漏洞扫描", assigner_id=lao_xing.id, assignee_id=xiao_xing.id, group_id=group.id, priority="urgent" ) if task2: print(f" ✅ 任务创建: {task2['task_id']}") print(f" 标题: {task2['title']}") print(f" 指派给: {task2['assignee_name']}") print(f" 优先级: {task2['priority']}") tasks_created.append(task2) if lao_xing and xiao_chen and group: task3 = coordinator.assign_task( title="优化交易策略", description="根据最新市场数据优化自动交易策略参数", assigner_id=lao_xing.id, assignee_id=xiao_chen.id, group_id=group.id, priority="normal" ) if task3: print(f" ✅ 任务创建: {task3['task_id']}") print(f" 标题: {task3['title']}") print(f" 指派给: {task3['assignee_name']}") tasks_created.append(task3) print_section("任务列表") tasks = TaskManager.get_all() print(f" {'任务ID':20} {'标题':22} {'状态':12} {'执行者'}") print(" " + "-" * 65) status_emoji = { TaskStatus.PENDING: "⏳", TaskStatus.IN_PROGRESS: "🔄", TaskStatus.COMPLETED: "✅", TaskStatus.CANCELLED: "❌" } for task in tasks: emoji = status_emoji.get(task.status, "❓") title = task.title[:20] + ".." if len(task.title) > 22 else task.title print(f" {task.task_id:20} {title:22} {emoji} {task.status:10} {task.assignee_name}") time.sleep(1) print_section("开始执行任务") if tasks_created: task = TaskManager.get_by_task_id(tasks_created[0]['task_id']) if task and xiao_jin: TaskManager.update_status(task.task_id, TaskStatus.IN_PROGRESS, xiao_jin.id, "开始分析报告") print(f" 🔄 任务 {task.task_id} 状态更新为: 进行中") print_section("完成任务") if tasks_created and xiao_jin: result = coordinator.complete_task( task_id=tasks_created[0]['task_id'], agent_id=xiao_jin.id, result="报告已完成!科技股本周上涨3.2%,新能源板块表现突出。" ) if result: print(f" ✅ 任务 {tasks_created[0]['task_id']} 已完成") time.sleep(1) # ========== 5. 决策管理 ========== print_header("5️⃣ 决策管理") print_section("提出决策") if lao_xing and group: decision = coordinator.propose_decision( title="是否升级服务器配置", description="当前服务器负载接近80%,建议升级配置以应对业务增长。预算约10万元。", proposer_id=lao_xing.id, group_id=group.id ) if decision: print(f" ✅ 决策提议: {decision['decision_id']}") print(f" 标题: {decision['title']}") print(f" 状态: {decision['status']}") time.sleep(0.5) print_section("投票") if decision: # 小邢投票赞成 if xiao_xing: coordinator.vote_decision( decision_id=decision['decision_id'], agent_id=xiao_xing.id, vote="for", comment="同意升级,现在负载确实偏高,升级能提升稳定性" ) print(f" 🗳️ 小邢 投票: 👍 赞成") time.sleep(0.2) # 小金投票赞成 if xiao_jin: coordinator.vote_decision( decision_id=decision['decision_id'], agent_id=xiao_jin.id, vote="for", comment="支持升级,业务增长需要更好的基础设施" ) print(f" 🗳️ 小金 投票: 👍 赞成") time.sleep(0.2) # 小陈投票反对 if xiao_chen: coordinator.vote_decision( decision_id=decision['decision_id'], agent_id=xiao_chen.id, vote="against", comment="建议先优化代码和缓存策略,目前还有优化空间" ) print(f" 🗳️ 小陈 投票: 👎 反对") print_section("决策状态") if decision: updated = DecisionManager.get_by_decision_id(decision['decision_id']) if updated: print(f" 📊 {updated.title}") print(f" 赞成: {updated.votes_for} 票") print(f" 反对: {updated.votes_against} 票") print(f" 通过率: {updated.pass_rate:.1f}%") time.sleep(0.5) print_section("结束决策") if decision: final = coordinator.finalize_decision(decision['decision_id']) if final: result_text = "✅ 通过" if final['status'] == DecisionStatus.APPROVED else "❌ 未通过" print(f" {result_text}") print(f" 最终状态: {final['status']}") time.sleep(1) # ========== 6. 收件箱与历史 ========== print_header("6️⃣ 收件箱与消息历史") print_section("消息历史") if group: messages = MessageManager.get_group_messages(group.id, limit=10) print(f" 💬 '{group.name}' 最近消息:") print(" " + "-" * 60) for msg in reversed(messages[-5:]): # 最近5条 from_name = msg.from_agent_name or f"Agent-{msg.from_agent_id}" content = msg.content[:45] print(f" [{from_name:8}] {content}...") print_section("任务统计") task_stats = TaskManager.get_statistics() print(f" 总任务: {task_stats['total']}") print(f" ⏳ 待处理: {task_stats['pending']}") print(f" 🔄 进行中: {task_stats['in_progress']}") print(f" ✅ 已完成: {task_stats['completed']}") print_section("决策统计") decision_stats = DecisionManager.get_statistics() print(f" 总决策: {decision_stats['total']}") print(f" 📝 提议中: {decision_stats['proposed']}") print(f" 💬 讨论中: {decision_stats['discussing']}") print(f" ✅ 已通过: {decision_stats['approved']}") print(f" ❌ 已拒绝: {decision_stats['rejected']}") # 结束 print_header("✨ 演示完成") print(""" 演示结束!系统的核心功能都已展示: ✅ Agent 管理与在线状态 ✅ 群组创建与成员管理 ✅ 消息发送与 @提及通知 ✅ 任务指派、进度跟踪、完成 ✅ 决策提议、投票、结果统计 ✅ 消息历史与统计信息 接下来你可以: 1. 运行 'python chat.py' 进入交互式 CLI 体验 2. 运行 'python main.py' 使用命令行工具 3. 查看 README.md 了解更多使用方法 """) coordinator.stop() if __name__ == "__main__": try: demo() except KeyboardInterrupt: print("\n\n演示已取消") except Exception as e: print(f"\n❌ 演示出错: {e}") import traceback traceback.print_exc()
-
-
SKILL.md 8 KB
--- name: agent-network description: Multi-Agent group chat collaboration system inspired by DingTalk/Lark. Enables AI agents to chat in groups, @mention each other, assign tasks, make decisions via voting, and collaborate. Use when building multi-agent systems that need structured communication, task delegation, decision making, or group coordination. --- # Agent Network - Multi-Agent Collaboration System A complete multi-agent group chat and collaboration platform that allows AI agents to communicate, coordinate, and collaborate in a structured environment similar to enterprise chat platforms like DingTalk or Lark. ## What This Skill Provides - **Group Chat System** - Multiple agents can chat in groups with message history - **@Mentions** - Agents can @mention each other to trigger notifications - **Task Management** - Create, assign, track, and complete tasks - **Decision Voting** - Propose decisions and vote (for/against/abstain) - **Inbox Notifications** - Unread message tracking and notification center - **Online Status** - Real-time agent online/offline status - **Central Coordinator** - Message routing and agent lifecycle management ## Quick Start ```python from agent_network import AgentManager, GroupManager, MessageManager, TaskManager, DecisionManager, get_coordinator # Initialize default agents from agent_network import init_default_agents init_default_agents() # Get the coordinator coordinator = get_coordinator() # Register agents coordinator.register_agent(agent_id=1) coordinator.register_agent(agent_id=2) # Create a group group = GroupManager.create("Dev Team", owner_id=1, description="Development team chat") GroupManager.add_member(group.id, agent_id=2) # Send a message with @mention MessageManager.send_message( from_agent_id=1, content="@小邢 Please check the server status", group_id=group.id ) # Assign a task task = TaskManager.create( title="Fix login bug", assigner_id=1, assignee_id=2, description="Users can't login with SSO", priority="high" ) # Create a decision decision = DecisionManager.create( title="Adopt new database?", description="Should we migrate to distributed database?", proposer_id=1, group_id=group.id ) # Vote on decision DecisionManager.vote(decision.id, agent_id=2, vote="for", comment="Agreed, better performance") ``` ## Core Components ### 1. Agent Management (`agent_manager.py`) Register and manage agents with online/offline status: ```python from agent_network import AgentManager # Register new agent agent = AgentManager.register("NewAgent", "Developer", "Backend specialist") # Set status AgentManager.go_online(agent.id) AgentManager.go_offline(agent.id) # Get online agents online = AgentManager.get_online_agents() ``` ### 2. Group Management (`group_manager.py`) Create groups and manage membership: ```python from agent_network import GroupManager # Create group group = GroupManager.create("Project Alpha", owner_id=1) # Add members GroupManager.add_member(group.id, agent_id=2) GroupManager.add_member(group.id, agent_id=3) # List members members = GroupManager.get_members(group.id) online_members = GroupManager.list_online_members(group.id) ``` ### 3. Message System (`message_manager.py`) Send messages with @mention support: ```python from agent_network import MessageManager # Send message msg = MessageManager.send_message( from_agent_id=1, content="Hello team!", group_id=1 ) # @mention automatically detected msg = MessageManager.send_message( from_agent_id=1, content="@Alice @Bob Please review this", group_id=1 ) # Get message history messages = MessageManager.get_group_messages(group_id=1, limit=50) # Search messages results = MessageManager.search_messages("keyword", group_id=1) # Get unread count unread = MessageManager.get_unread_count(agent_id=1) inbox = MessageManager.get_agent_inbox(agent_id=1, only_unread=True) ``` ### 4. Task Management (`task_manager.py`) Full task lifecycle: ```python from agent_network import TaskManager # Create task task = TaskManager.create( title="Implement API", assigner_id=1, assignee_id=2, description="Build REST endpoints", priority="high", # low/normal/high/urgent due_date="2026-02-15" ) # Update status TaskManager.start_task(task.id, agent_id=2) TaskManager.complete_task(task.id, agent_id=2, result="All tests passed") # Add comments TaskManager.add_comment(task.id, agent_id=2, "50% complete") # List tasks all_tasks = TaskManager.get_all() my_tasks = TaskManager.get_agent_tasks(agent_id=2, status="pending") ``` ### 5. Decision Voting (`decision_manager.py`) Collaborative decision making: ```python from agent_network import DecisionManager # Create proposal decision = DecisionManager.create( title="Use microservices?", description="Should we refactor to microservices?", proposer_id=1, group_id=1 ) # Vote DecisionManager.vote(decision.id, agent_id=2, vote="for", comment="Better scalability") DecisionManager.vote(decision.id, agent_id=3, vote="against") # Update status DecisionManager.update_status(decision.id, "approved", updater_id=1) # Check results decision = DecisionManager.get_by_id(decision.id) print(f"Pass rate: {decision.pass_rate}%") ``` ### 6. Central Coordinator (`coordinator.py`) High-level coordination with automatic message routing: ```python from agent_network import get_coordinator coord = get_coordinator() # Register with message handler def my_handler(msg_dict): print(f"Received: {msg_dict['content']}") coord.register_agent(agent_id=1, message_handler=my_handler) # Send through coordinator (auto-routes to handlers) coord.send_message(from_agent_id=1, content="Hello", group_id=1) # Task coordination task = coord.assign_task( title="Deploy app", description="Deploy to production", assigner_id=1, assignee_id=2 ) # Decision coordination decision = coord.propose_decision( title="Release v2.0?", description="Ready for release?", proposer_id=1 ) coord.vote_decision(decision['id'], agent_id=2, vote="for") ``` ## CLI Usage Interactive CLI for testing: ```bash # Run demo python demo.py # Interactive CLI python cli.py # Commands in CLI: # - Select agent to login # - Enter groups to chat # - Type /task to create tasks # - Type /decision to create votes # - Type @AgentName to mention ``` ## Default Agents Six pre-configured agents: | Agent | Role | Description | |-------|------|-------------| | 老邢 (Lao Xing) | Manager | Overall coordination | | 小邢 (Xiao Xing) | DevOps | Development and operations | | 小金 (Xiao Jin) | Finance Analyst | Market analysis | | 小陈 (Xiao Chen) | Trader | Trading execution | | 小影 (Xiao Ying) | Designer | Design and content | | 小视频 (Xiao Shipin) | Video | Video production | ## Database Schema SQLite database with tables: - `agents` - Agent profiles and status - `groups` - Group definitions - `group_members` - Membership relations - `messages` - Chat messages with types - `tasks` - Task tracking - `task_comments` - Task discussions - `decisions` - Decision proposals - `decision_votes` - Voting records - `agent_inbox` - Notification inbox ## Integration with OpenClaw Use with `sessions_spawn` for true multi-agent workflows: ```python # When a task is assigned, spawn a sub-agent if new_task: sessions_spawn( agentId="xiaoxing", task=new_task.description, label=f"task-{new_task.task_id}" ) ``` ## Files Reference - `scripts/agent_network/` - Python modules - `__init__.py` - Package exports - `database.py` - SQLite management - `agent_manager.py` - Agent CRUD - `group_manager.py` - Group management - `message_manager.py` - Messaging system - `task_manager.py` - Task management - `decision_manager.py` - Voting system - `coordinator.py` - Central coordinator - `scripts/cli.py` - Interactive CLI - `scripts/demo.py` - Demo script - `references/schema.sql` - Database schema - `assets/` - Templates (optional) ## Advanced Usage See `references/ADVANCED.md` for: - Custom agent handlers - Webhook integrations - Message filtering - Custom workflows -
_meta.json 132 B
{ "ownerId": "kn7erwv38d0jvsrd0cn6bc841580y0f7", "slug": "agent-network", "version": "1.1.0", "publishedAt": 1770800715451 }
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.