# Robot Agent ## 1. What is it? A **Robot Agent** is an AI team member. It works on its own, makes decisions, and runs tasks without waiting for user input. **Key points:** - Belongs to a Team, managed like human members - Has clear job duties (e.g., "Sales Manager: track KPIs, make reports") - Created and deleted via Team API - Runs on schedule, or when triggered by humans or events - Learns from each run, stores knowledge in private KB --- ## 2. Architecture ### 2.1 System Flow > **Architecture Note:** All trigger types flow through Manager. > > - Clock: `Manager.Tick()` (internal ticker) > - Human: `Manager.Intervene()` (API call) > - Event: `Manager.HandleEvent()` (webhook/db trigger) > > The `trigger/` package provides utilities only (validation, clock matching, execution control). ```mermaid flowchart TB subgraph Triggers["Triggers"] WC[/"⏰ Clock"/] HI[/"πŸ‘€ Human"/] EV[/"πŸ“‘ Event"/] end subgraph Manager["Manager (Central Orchestrator)"] TC{"Enabled?"} Cache[("Cache")] Dedup{"Dedup?"} Queue["Queue"] end subgraph Pool["Workers"] W1["Worker"] W2["Worker"] W3["Worker"] end subgraph Executor["Executor"] TT{"Trigger?"} P0["P0: Inspiration"] P1["P1: Goals"] P2["P2: Tasks"] P3["P3: Run"] P4["P4: Deliver"] P5["P5: Learn"] end subgraph Storage["Storage"] KB[("KB")] DB[("DB")] end WC --> TC HI & EV --> TC TC -->|Yes| Cache TC -->|No| X[/Skip/] Cache --> Dedup Dedup -->|OK| Queue Dedup -->|Dup| Cache Queue --> W1 & W2 & W3 W1 & W2 & W3 --> TT TT -->|Clock| P0 TT -->|Human/Event| P1 P0 --> P1 --> P2 --> P3 --> P4 --> P5 P5 --> KB & DB KB -.->|History| P0 ``` ### 2.2 Executor Modes Executor supports multiple execution modes for different use cases: | Mode | Use Case | Status | | -------- | --------------------------------------- | ------------------ | | Standard | Production with real Agent calls | βœ… Implemented | | DryRun | Tests, demos, preview without LLM calls | βœ… Implemented | | Sandbox | Container-isolated for untrusted code | ⬜ Not Implemented | **Standard Mode:** Real execution with LLM calls, full phase execution, logging via kun/log. **DryRun Mode:** Simulated execution without LLM calls. Used for: - Unit tests and integration tests - Demo and preview modes - Scheduling and concurrency testing **Sandbox Mode (Future):** Container-level isolation (Docker/gVisor/Firecracker) for: - Untrusted robot configurations - Multi-tenant environments - Resource-limited execution > **⚠️ Sandbox requires infrastructure support.** Current placeholder behaves like DryRun. ### 2.3 Team Structure Uses existing `__yao.member` model (`yao/models/member.mod.yao`): ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Team β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Robot Members β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ β”‚ β”‚Sales Managerβ”‚ β”‚Data Analyst β”‚ β”‚CS Specialistβ”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β€’ Track KPIsβ”‚ β”‚ β€’ Analyze β”‚ β”‚ β€’ Tickets β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β€’ Reports β”‚ β”‚ β€’ Reports β”‚ β”‚ β€’ Inquiries β”‚ β”‚ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ User Members β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ β”‚ β”‚ John (Owner)β”‚ β”‚ Jane (Admin)β”‚ β”‚ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` **Key fields in `__yao.member` for robot agents:** | Field | Type | Description | | ----------------- | ------ | ----------------------------------------------------------- | | `member_type` | enum | `user` \| `robot` | | `autonomous_mode` | bool | Enable robot execution | | `robot_config` | JSON | Agent configuration (see section 5) | | `robot_status` | enum | `idle` \| `working` \| `paused` \| `error` \| `maintenance` | | `system_prompt` | text | Identity & role prompt | | `robot_email` | string | Robot's email address for sending emails (From address) | | `agents` | JSON | Accessible agents list | | `mcp_servers` | JSON | Accessible MCP servers | | `manager_id` | string | Direct manager user ID | --- ## 3. How It Works ### 3.1 Flow: Trigger β†’ Schedule β†’ Run ```mermaid sequenceDiagram autonumber participant T as Trigger participant M as Manager participant S as Scheduler participant W as Worker participant E as Executor participant A as Phase Agents participant KB as KB T->>M: Event M->>M: Check enabled M->>M: Get from cache M->>M: Check dedup M->>S: Submit S->>S: Check quota S->>S: Sort by priority S->>W: Dispatch W->>E: Run alt Clock trigger E->>A: P0: Inspiration (with clock context) A-->>E: Report end loop P1 to P5 E->>A: Call agent A-->>E: Result end E->>KB: Save learning E-->>W: Done ``` ### 3.2 Triggers | Type | What | Config | Handler | | --------- | ----------------------------- | -------------------- | ----------------------- | | **Clock** | Timer (times/interval/daemon) | `triggers.clock` | `Manager.Tick()` | | **Human** | Manual action | `triggers.intervene` | `Manager.Intervene()` | | **Event** | Webhook, DB change | `triggers.event` | `Manager.HandleEvent()` | All on by default. Turn off per agent: ```yaml triggers: clock: { enabled: true } intervene: { enabled: true, actions: ["task.add", "goal.adjust"] } event: { enabled: false } ``` ### 3.3 Concurrency Two levels to prevent one agent from using all resources: ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Global Pool (10 workers) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β–Ό β–Ό β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Sales Manager β”‚ β”‚ Data Analyst β”‚ β”‚ CS Specialist β”‚ β”‚ Limit: 3 β”‚ β”‚ Limit: 2 β”‚ β”‚ Limit: 3 β”‚ β”‚ Now: 2 βœ“ β”‚ β”‚ Now: 2 (full) β”‚ β”‚ Now: 1 βœ“ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` ### 3.4 Dedup **Fast check** (in memory): ```go key := memberID + ":" + triggerType + ":" + window if has(key) { skip } ``` **Smart check** (for goals/tasks): - Dedup Agent looks at history - Returns: `skip` | `merge` | `proceed` ### 3.5 Cache Keeps agents in memory. No DB query on each tick: ```go type AgentCache struct { agents map[string]*Agent // member_id -> agent byTeam map[string][]string // team_id -> member_ids } // Refresh: on start, on change, every hour ``` --- ## 4. Phases ### 4.1 Overview ``` Clock: P0 β†’ P1 β†’ P2 β†’ P3 β†’ P4 β†’ P5 Human/Event: P1 β†’ P2 β†’ P3 β†’ P4 β†’ P5 ``` | Phase | Agent | In | Out | When | | ----- | ----------- | ------------------- | --------------- | ---------- | | P0 | Inspiration | Clock + Data + News | Report | Clock only | | P1 | Goal Gen | Report + history | Goals | Always | | P2 | Task Plan | Goals + tools | Tasks | Always | | P3 | Run + Valid | Tasks + Experts | TaskResults | Always | | P4 | Delivery | All results | Email/Webhook/Process | Always | | P5 | Learning | Summary | KB entries | Always | ### 4.2 P0: Inspiration (Clock only) **Skipped for Human/Event triggers.** They already have clear intent. Gathers info to help make good goals. **Clock context is key input** - Agent knows what time it is and can decide what to do (e.g., 5pm Friday β†’ write weekly report). ```go type InspirationReport struct { Clock *ClockContext `json:"clock"` // time context Content string `json:"content"` // markdown text for LLM } // Content is markdown like: // ## Summary // ... // ## Highlights // - [High] Sales up 50% // ## Opportunities / Risks / World News / Pending // ... type ClockContext struct { Now time.Time // Current time Hour int // 0-23 DayOfWeek string // Monday, Tuesday... DayOfMonth int // 1-31 IsWeekend bool IsMonthStart bool // 1st-3rd IsMonthEnd bool // last 3 days IsQuarterEnd bool // Agent uses this to decide: "It's 5pm Friday, time for weekly report" } ``` **Sources:** - **Clock**: Current time, day of week, month end, etc. - Internal: Data changes, events, feedback, pending work - External: Web search (news, competitors) ### 4.3 P1: Goals **For Clock:** Uses inspiration report (with clock context) to make goals. Agent decides based on time what's important now. **For Human/Event:** Uses the input directly as goals (or to generate goals). ```go type Goals struct { Content string // markdown text (for LLM) Delivery *DeliveryTarget // where to send results (for P4) } type DeliveryTarget struct { Type DeliveryType // Preferred delivery type (P4 will use Delivery Center) Recipients []string // email addresses, webhook URLs, user IDs Format string // markdown | html | json | text Template string // template name Options map[string]interface{} } ``` **Example prompt:** ``` You are [Sales Manager]. Your job: [track KPIs, make reports]. ## Report ### Key Items - [High] Data: 15 new sales (+50%) - [High] Deadline: Friday report due - [High] News: Competitor launched product ### Chances - Sales up 20% vs last week - Market growing Make today's goals. ``` **Note:** Validation criteria (`ExpectedOutput`, `ValidationRules`) are defined at the **Task level** (P2), not Goals level. This allows each task to have specific validation rules for P3. ### 4.4 P2: Tasks P2 Agent reads Goals markdown and breaks into executable tasks: ```go type Task struct { ID string // unique task ID Description string // human-readable task description (for UI display) Messages []context.Message // original input (text, images, files, audio) GoalRef string // reference to goal (e.g., "Goal 1") Source TaskSource // auto | human | event ExecutorType ExecutorType // assistant | mcp | process ExecutorID string // agent ID or mcp tool name Args []any // arguments for executor Order int // execution order // Validation criteria (used in P3) ExpectedOutput string // what the task should produce ValidationRules []string // specific checks to perform } ``` ### 4.5 P3: Run **Architecture:** P3 uses a modular design with three components: ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ run.go (P3 Entry) β”‚ β”‚ - RunConfig: ContinueOnFailure, ValidationThreshold, β”‚ β”‚ MaxTurnsPerTask β”‚ β”‚ - RunExecution: main loop with task dependency passing β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β–Ό β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ runner.go β”‚ β”‚ validator.go β”‚ β”‚ - Runner β”‚ β”‚ - Validator β”‚ β”‚ - Multi-turn β”‚ β”‚ - Two-layer β”‚ β”‚ conversation β”‚ β”‚ - Rule+Semanticβ”‚ β”‚ - Task context β”‚ β”‚ - NeedReply β”‚ β”‚ building β”‚ β”‚ - ReplyContent β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β–Ό β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ yao/assert β”‚ β”‚ β”‚ - Asserter β”‚ β”‚ β”‚ - 8 types β”‚ β”‚ β”‚ - Extensible β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Executor Types β”‚ β”‚ - ExecutorAssistant β†’ Multi-turn AI β”‚ β”‚ - ExecutorMCP β†’ Single-call MCP tool β”‚ β”‚ - ExecutorProcess β†’ Single-call Process β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` **Execution Flow:** For each task: 1. **Build Context**: Include previous task results as context 2. **Execute**: Call appropriate executor (Assistant/MCP/Process) 3. **Validate**: Use two-layer validation (rule-based + semantic) 4. **Continue or Complete**: - For Assistant tasks: If `NeedReply`, continue conversation with `ReplyContent` - For MCP/Process tasks: Single-call execution, no multi-turn 5. **Update**: Set task status and store result **Task Dependency**: Previous task results are automatically passed as context to subsequent tasks via `Runner.BuildTaskContext()` and formatted using `FormatPreviousResultsAsContext()`. **Two-Layer Validation:** | Layer | Method | Speed | Use Case | |-------|--------|-------|----------| | 1. Rule-based | `yao/assert` | Fast | Type check, contains, regex, json_path | | 2. Semantic | Validation Agent | Slow | ExpectedOutput, complex criteria | **Executor Types:** | Type | ExecutorID Format | Example | |------|-------------------|---------| | `assistant` | Agent ID | `experts.text-writer` | | `mcp` | `mcp_server.mcp_tool` | `ark.image.text2img.generate` | | `process` | Process name | `models.user.Find` | **MCP Task Fields:** For MCP tasks, three fields are required: - `executor_id`: Combined format `mcp_server.mcp_tool` - `mcp_server`: MCP server/client ID (e.g., `ark.image.text2img`) - `mcp_tool`: Tool name within the server (e.g., `generate`) **Multi-Turn Conversation Flow:** For assistant tasks, P3 uses a multi-turn conversation approach: 1. **Call**: Call assistant and get result 2. **Validate**: Validate result (determines: passed, complete, needReply, replyContent) 3. **Reply**: If needReply, continue conversation with replyContent 4. **Repeat**: Until complete or max turns exceeded The `Validator.ValidateWithContext()` method determines: - `Complete`: Whether the expected result is obtained - `NeedReply`: Whether to continue conversation - `ReplyContent`: What to send in the next turn (validation feedback, clarification request, etc.) This replaces the traditional retry mechanism with intelligent conversation continuation. ```go // RunConfig configures P3 execution behavior type RunConfig struct { ContinueOnFailure bool // continue to next task even if current fails (default: false) ValidationThreshold float64 // minimum score to pass validation (default: 0.6) MaxTurnsPerTask int // max conversation turns per task (default: 10) } // ValidationResult with multi-turn conversation support type ValidationResult struct { // Basic validation result Passed bool // overall validation passed Score float64 // 0-1 confidence score Issues []string // what failed Suggestions []string // how to improve Details string // detailed report (markdown) // Execution state (for multi-turn conversation control) Complete bool // whether expected result is obtained NeedReply bool // whether to continue conversation ReplyContent string // content for next turn (if NeedReply) } ``` **yao/assert Package:** Universal assertion library supporting 8 types: | Type | Description | Example | |------|-------------|---------| | `equals` | Exact match | `{"type": "equals", "value": "success"}` | | `contains` | Substring check | `{"type": "contains", "value": "total"}` | | `not_contains` | Negative check | `{"type": "not_contains", "value": "error"}` | | `json_path` | JSON path extraction | `{"type": "json_path", "path": "data.count", "value": 10}` | | `regex` | Pattern matching | `{"type": "regex", "value": "^[A-Z].*"}` | | `type` | Type checking | `{"type": "type", "value": "array"}` | | `script` | Custom script | `{"type": "script", "script": "scripts.validate"}` | | `agent` | AI validation | `{"type": "agent", "use": "validator"}` | ### 4.6 P4: Deliver P4 generates delivery content and pushes to Delivery Center. **Agent only generates content, Delivery Center decides channels.** **Architecture:** ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ P4 Delivery Agent β”‚ β”‚ Role: Generate content only (Summary, Body, Attachments) β”‚ β”‚ NOT responsible for: Channel selection β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ DeliveryRequest β”‚ β”‚ - Content: Summary, Body, Attachments β”‚ β”‚ - Context: member_id, execution_id, trigger, team β”‚ β”‚ (No Channels - Delivery Center decides) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Delivery Center β”‚ β”‚ Role: β”‚ β”‚ 1. Read Robot/User delivery preferences β”‚ β”‚ 2. Decide which channels to use β”‚ β”‚ 3. Execute delivery (email, webhook, process) β”‚ β”‚ 4. Future: auto-notify based on user subscriptions β”‚ β”‚ β”‚ β”‚ (Current: internal, future: yao/delivery) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` **Key Design:** - **Separation of concerns**: Agent generates content, Delivery Center handles channels - **User preferences**: Channels decided by Robot/User configuration, not Agent - **Automatic delivery**: If webhook configured, every execution pushes automatically - **Future-ready**: Delivery Center can be extracted to `yao/delivery` package **Delivery Request Structure:** ```go // DeliveryRequest - pushed to Delivery Center // No Channels field - Delivery Center decides based on preferences type DeliveryRequest struct { Content *DeliveryContent `json:"content"` // Agent-generated content Context *DeliveryContext `json:"context"` // Tracking info } // DeliveryContent - content generated by Delivery Agent type DeliveryContent struct { Summary string `json:"summary"` // Brief 1-2 sentence summary Body string `json:"body"` // Full markdown report Attachments []DeliveryAttachment `json:"attachments,omitempty"` // Output artifacts } // DeliveryAttachment - task output attachment with metadata type DeliveryAttachment struct { Title string `json:"title"` // Human-readable title Description string `json:"description,omitempty"` // What this artifact is TaskID string `json:"task_id,omitempty"` // Which task produced this File string `json:"file"` // Wrapper: __:// } // DeliveryContext - tracking and audit info type DeliveryContext struct { MemberID string `json:"member_id"` // Robot member ID (globally unique) ExecutionID string `json:"execution_id"` TriggerType TriggerType `json:"trigger_type"` TeamID string `json:"team_id"` } ``` **File Wrapper Format:** Attachments use the standard `yao/attachment` wrapper format: - Format: `__://` - Example: `__yao.attachment://ccd472d11feb96e03a3fc468f494045c` - Parse: `attachment.Parse(value)` β†’ `(uploader, fileID, isWrapper)` - Read: `attachment.Base64(ctx, value)` β†’ base64 content **Delivery Channels (Delivery Center decides):** | Channel | Description | Multiple Targets | |---------|-------------|------------------| | `email` | Send via yao/messenger | βœ… Multiple recipients/emails | | `webhook` | POST to external URL | βœ… Multiple URLs | | `process` | Yao Process call | βœ… Multiple processes | | `notify` | In-app notification | Future (auto by subscriptions) | **Delivery Agent:** The Delivery Agent **only generates content**, does NOT decide channels: ```go // Delivery Agent Input type DeliveryAgentInput struct { Robot *Robot `json:"robot"` TriggerType TriggerType `json:"trigger"` Inspiration *InspirationReport `json:"inspiration"` // P0 Goals *Goals `json:"goals"` // P1 Tasks []Task `json:"tasks"` // P2 Results []TaskResult `json:"results"` // P3 } // Delivery Agent Output - only content, no channels type DeliveryAgentOutput struct { Content *DeliveryContent `json:"content"` } ``` **Example Agent Output:** ```json { "content": { "summary": "Sales report completed: 15 new leads processed", "body": "## Weekly Sales Report\n\n### Summary\n...", "attachments": [ {"title": "Sales Report.pdf", "file": "__yao.attachment://abc123"}, {"title": "Lead Analysis.xlsx", "file": "__yao.attachment://def456"} ] } } ``` **Delivery Result:** ```go // DeliveryResult - returned by Delivery Center type DeliveryResult struct { RequestID string `json:"request_id"` // Delivery request ID Content *DeliveryContent `json:"content"` // Agent-generated content Results []ChannelResult `json:"results,omitempty"` // Results per channel Success bool `json:"success"` // Overall success Error string `json:"error,omitempty"` // Error if failed SentAt *time.Time `json:"sent_at,omitempty"` // When delivery completed } // ChannelResult - result for a single delivery target type ChannelResult struct { Type DeliveryType `json:"type"` // email | webhook | process Target string `json:"target"` // Target identifier (email, URL, process name) Success bool `json:"success"` // Whether delivery succeeded Recipients []string `json:"recipients,omitempty"` // Who received (for email) Details interface{} `json:"details,omitempty"` // Channel-specific response Error string `json:"error,omitempty"` // Error message if failed SentAt *time.Time `json:"sent_at,omitempty"` // When this target was delivered } ``` **Config (Delivery Preferences):** Robot config defines delivery **preferences** (Delivery Center reads and executes). Each channel supports **multiple targets**: ```yaml delivery: preferences: email: enabled: true targets: # Multiple email targets - to: ["manager@company.com"] cc: ["team@company.com"] - to: ["ceo@company.com"] subject_template: "Executive Summary" webhook: enabled: true targets: # Multiple webhook URLs - url: "https://slack.com/webhook/sales" - url: "https://feishu.cn/webhook/reports" headers: {"X-Custom": "value"} process: enabled: true targets: # Multiple Yao Process calls - name: "orders.UpdateStatus" args: ["completed"] - name: "audit.LogDelivery" # Note: notify handled by Delivery Center based on user subscriptions (future) ``` **Use Cases:** | Scenario | Channels | Description | |----------|----------|-------------| | Event callback | `process` | DB change β†’ Robot β†’ Update data via Process | | Multi-channel notify | `email` + `webhook` | Send to multiple emails and Slack/飞书 | | Data pipeline | `process` | Robot result β†’ Save to DB β†’ Update dashboard | ### 4.7 P5: Learn Save to KB: | Type | Examples | | ----------- | ------------------------ | | `execution` | What worked, what failed | | `feedback` | Errors, fixes | | `insight` | Patterns, tips | --- ## 5. Config ### 5.1 Structure ```go type Config struct { Triggers *Triggers `json:"triggers,omitempty"` Clock *Clock `json:"clock,omitempty"` Identity *Identity `json:"identity"` Quota *Quota `json:"quota"` KB *KB `json:"kb,omitempty"` // shared KB (same as assistant) DB *DB `json:"db,omitempty"` // shared DB (same as assistant) Learn *Learn `json:"learn,omitempty"` // learning for private KB Resources *Resources `json:"resources"` Delivery *DeliveryPreferences `json:"delivery,omitempty"` Events []Event `json:"events,omitempty"` Executor *Executor `json:"executor,omitempty"` // executor mode settings DefaultLocale string `json:"default_locale,omitempty"` // default language for clock/event triggers ("en-US", "zh-CN") } ``` ### 5.2 Types ```go // Phase - execution phase enum type Phase string const ( PhaseInspiration Phase = "inspiration" // P0: Clock only PhaseGoals Phase = "goals" // P1 PhaseTasks Phase = "tasks" // P2 PhaseRun Phase = "run" // P3 (execution + validation) PhaseDelivery Phase = "delivery" // P4 PhaseLearning Phase = "learning" // P5 ) // AllPhases for iteration var AllPhases = []Phase{ PhaseInspiration, PhaseGoals, PhaseTasks, PhaseRun, PhaseDelivery, PhaseLearning, } // ClockMode - clock trigger mode enum type ClockMode string const ( ClockModeTimes ClockMode = "times" // run at specific times ClockModeInterval ClockMode = "interval" // run every X duration ClockModeDaemon ClockMode = "daemon" // run continuously ) // DeliveryType - output delivery type enum type DeliveryType string const ( DeliveryEmail DeliveryType = "email" // Email via yao/messenger DeliveryWebhook DeliveryType = "webhook" // POST to external URL DeliveryProcess DeliveryType = "process" // Yao Process call DeliveryNotify DeliveryType = "notify" // In-app notification (future) ) // ExecStatus - execution status enum type ExecStatus string const ( ExecPending ExecStatus = "pending" ExecRunning ExecStatus = "running" ExecCompleted ExecStatus = "completed" ExecFailed ExecStatus = "failed" ExecCancelled ExecStatus = "cancelled" ) // RobotStatus - matches __yao.member.robot_status enum type RobotStatus string const ( RobotIdle RobotStatus = "idle" // ready to run RobotWorking RobotStatus = "working" // currently executing RobotPaused RobotStatus = "paused" // manually paused RobotError RobotStatus = "error" // encountered error RobotMaintenance RobotStatus = "maintenance" // under maintenance ) // Triggers - all on by default type Triggers struct { Clock *Trigger `json:"clock,omitempty"` Intervene *Trigger `json:"intervene,omitempty"` Event *Trigger `json:"event,omitempty"` } type Trigger struct { Enabled bool `json:"enabled"` Actions []string `json:"actions,omitempty"` // for intervene } // Clock - when to wake up type Clock struct { Mode ClockMode `json:"mode"` Times []string `json:"times"` // for times: ["09:00", "14:00"] Days []string `json:"days"` // ["Mon", "Tue"...] or ["*"] Every string `json:"every"` // for interval: "30m", "1h" TZ string `json:"tz"` // Asia/Shanghai Timeout string `json:"timeout"` // max run time } // Identity type Identity struct { Role string `json:"role"` Duties []string `json:"duties"` Rules []string `json:"rules"` } // Quota type Quota struct { Max int `json:"max"` // max running (default: 2) Queue int `json:"queue"` // queue size (default: 10) Priority int `json:"priority"` // 1-10 (default: 5) } // KB // KB - shared knowledge base (same as assistant) type KB struct { Collections []string `json:"collections,omitempty"` // KB collection IDs Options map[string]interface{} `json:"options,omitempty"` } // DB - shared database (same as assistant) type DB struct { Models []string `json:"models,omitempty"` // database model names Options map[string]interface{} `json:"options,omitempty"` } // Learn - learning config for robot's private KB // Private KB auto-created: robot_{team_id}_{member_id}_kb type Learn struct { On bool `json:"on"` Types []string `json:"types"` // execution, feedback, insight Keep int `json:"keep"` // days, 0 = forever } // Resources type Resources struct { Phases map[Phase]string `json:"phases,omitempty"` // optional, defaults to __yao.{phase} Agents []string `json:"agents"` MCP []MCP `json:"mcp"` } type MCP struct { ID string `json:"id"` Tools []string `json:"tools,omitempty"` // empty = all } // DeliveryPreferences - Robot delivery preferences (read by Delivery Center) // Each channel supports multiple targets type DeliveryPreferences struct { Email *EmailPreference `json:"email,omitempty"` Webhook *WebhookPreference `json:"webhook,omitempty"` Process *ProcessPreference `json:"process,omitempty"` // notify is handled automatically based on user subscriptions } type EmailPreference struct { Enabled bool `json:"enabled"` Targets []EmailTarget `json:"targets"` } type EmailTarget struct { To []string `json:"to"` // Recipient addresses Template string `json:"template,omitempty"` // Email template ID Subject string `json:"subject,omitempty"` // Subject template } type WebhookPreference struct { Enabled bool `json:"enabled"` Targets []WebhookTarget `json:"targets"` } type WebhookTarget struct { URL string `json:"url"` // Webhook URL Method string `json:"method,omitempty"` // HTTP method (default: POST) Headers map[string]string `json:"headers,omitempty"` // Custom headers Secret string `json:"secret,omitempty"` // Signing secret } type ProcessPreference struct { Enabled bool `json:"enabled"` Targets []ProcessTarget `json:"targets"` } type ProcessTarget struct { Process string `json:"process"` // Yao Process name, e.g., "orders.UpdateStatus" Args []any `json:"args,omitempty"` // Additional arguments } // ExecutorMode - executor mode enum type ExecutorMode string const ( ExecutorStandard ExecutorMode = "standard" // real Agent calls (default) ExecutorDryRun ExecutorMode = "dryrun" // simulated, no LLM calls ExecutorSandbox ExecutorMode = "sandbox" // container-isolated (NOT IMPLEMENTED) ) // Executor - executor settings type Executor struct { Mode ExecutorMode `json:"mode,omitempty"` // standard | dryrun | sandbox MaxDuration string `json:"max_duration,omitempty"` // max execution time (e.g., "30m") } // Note: Sandbox mode requires container infrastructure (Docker/gVisor). // Current implementation falls back to DryRun behavior. // Monitor ``` ### 5.3 Example Example record in `__yao.member` table: ```json { "member_id": "mem_abc123", "team_id": "team_xyz", "member_type": "robot", "display_name": "Sales Bot", "autonomous_mode": true, "robot_status": "idle", "system_prompt": "You are a sales analyst...", "robot_config": { "triggers": { "clock": { "enabled": true }, "intervene": { "enabled": true }, "event": { "enabled": false } }, "clock": { "mode": "times", "times": ["09:00", "14:00", "17:00"], "days": ["Mon", "Tue", "Wed", "Thu", "Fri"], "tz": "Asia/Shanghai", "timeout": "30m" }, "identity": { "role": "Sales Analyst", "duties": ["Analyze sales", "Make weekly reports"], "rules": ["Only access sales data"] }, "quota": { "max": 2, "queue": 10, "priority": 5 }, "kb": { "collections": ["sales-policies", "products"] }, "db": { "models": ["sales", "customers"] }, "learn": { "on": true, "types": ["execution", "feedback", "insight"], "keep": 90 }, "resources": { "phases": { "inspiration": "__yao.inspiration", "goals": "__yao.goals", "tasks": "__yao.tasks", "validation": "__yao.validation", "delivery": "__yao.delivery", "learning": "__yao.learning" }, "agents": ["data-analyst", "chart-gen"], "mcp": [{ "id": "database", "tools": ["query"] }] }, "delivery": { "type": "email", "opts": { "to": ["manager@company.com"] } }, "executor": { "mode": "standard", "max_duration": "30m" } }, "agents": ["data-analyst", "chart-gen"], "mcp_servers": ["database"] } ``` --- ## 6. Lifecycle ### 6.1 Agent States ```mermaid stateDiagram-v2 [*] --> Idle: POST create Idle --> Working: trigger Working --> Idle: done Idle --> Paused: PATCH pause Working --> Paused: PATCH pause Paused --> Idle: PATCH resume Idle --> Error: error Working --> Error: error Error --> Idle: PATCH reset Idle --> [*]: DELETE Paused --> [*]: DELETE ``` | From | To | How | | ------- | ------- | --------------------------- | | - | idle | POST create | | idle | working | trigger (clock/human/event) | | working | idle | execution done | | idle | paused | PATCH robot_status="paused" | | paused | idle | PATCH robot_status="idle" | | any | error | execution error | | error | idle | PATCH robot_status="idle" | | any | deleted | DELETE | ### 6.2 On Create 1. Check config 2. Generate member_id if missing 3. Create KB: `robot_{team_id}_{member_id}_kb` 4. Add to cache 5. Set active ### 6.3 On Delete 1. Stop running executions 2. Remove from cache 3. Delete or archive KB 5. Soft delete record ### 6.4 Execution Flow Single execution flow, depends on trigger type: ```mermaid flowchart LR subgraph Trigger T{Trigger} end subgraph Schedule Path P0[P0: Inspiration] end subgraph Common Path P1[P1: Goals] P2[P2: Tasks] P3[P3: Run] P4[P4: Deliver] P5[P5: Learn] end T -->|Clock| P0 T -->|Human/Event| P1 P0 --> P1 P1 --> P2 --> P3 --> P4 --> P5 ``` ```mermaid stateDiagram-v2 [*] --> Triggered Triggered --> P0_Inspiration: Clock Triggered --> P1_Goals: Human/Event P0_Inspiration --> P1_Goals P1_Goals --> P2_Tasks P2_Tasks --> P3_Run P3_Run --> P4_Deliver P4_Deliver --> P5_Learn P5_Learn --> [*] ``` --- ## 7. Integrations ### 7.1 Execution Storage **Relationship:** 1 Robot : N Executions (concurrent) Each trigger creates a new Execution, stored in `ExecutionStore` (`__yao.agent_execution` table). Execution data includes: - Status and phase tracking - All phase outputs (Inspiration, Goals, Tasks, Results, Delivery, Learning) - Error information - Timestamps and progress Logging is handled by `kun/log` package for standard application logging. | List Execs | `job.ListExecutions(param, page, pagesize)` | | Get Exec | `job.GetExecution(execID, param)` | | Save Exec | `job.SaveExecution(exec)` | | List Logs | `job.ListLogs(param, page, pagesize)` | | Save Log | `job.SaveLog(log)` | | Push (start) | `j.Push()` | | Stop | `j.Stop()` | | Destroy | `j.Destroy()` | | Active Jobs | `job.GetActiveJobs()` | | Query by Cat | `job.ListJobs({Wheres: [{Column: "category_id", ...}]})` | ### 7.2 Private KB Made on robot member create: `robot_{team_id}_{member_id}_kb` **What it stores:** - `execution`: What worked, what failed - `feedback`: Errors, fixes - `insight`: Patterns, tips **When:** - Create: On robot member create - Update: After P5 - Clean: Based on `keep` days - Delete: On robot member delete ### 7.3 External Input **Types:** - `clock`: Timer (with time context) - `intervene`: Human action - `event`: Webhook, DB change - `callback`: Async result **Human actions (InterventionAction):** - `task.add`: Add a new task - `task.cancel`: Cancel a task - `task.update`: Update task details - `goal.adjust`: Modify current goal - `goal.add`: Add a new goal - `goal.complete`: Mark goal as complete - `goal.cancel`: Cancel a goal - `plan.add`: Schedule for later - `plan.remove`: Remove from plan queue - `plan.update`: Update planned item - `instruct`: Direct instruction to robot **Plan Queue:** - Holds tasks for later - Runs at next cycle start --- ## 8. API ### 8.1 Manager (Internal) > **Note:** Manager is the central orchestrator, handling all trigger types. ```go type Manager interface { // Lifecycle Start() error Stop() error // Clock trigger (internal, called by ticker) Tick(ctx *Context, now time.Time) error // Manual trigger (for testing/API) TriggerManual(ctx *Context, memberID string, trigger TriggerType, data interface{}) (string, error) // Human intervention (called by API) Intervene(ctx *Context, req *InterveneRequest) (*ExecutionResult, error) // Event trigger (called by webhook/db trigger) HandleEvent(ctx *Context, req *EventRequest) (*ExecutionResult, error) // Execution control PauseExecution(ctx *Context, execID string) error ResumeExecution(ctx *Context, execID string) error StopExecution(ctx *Context, execID string) error // Cache access Cache() Cache } ``` ### 8.2 Trigger (Integrated into Manager) > **Note:** Trigger logic is integrated into Manager, not a separate interface. > The `trigger/` package provides utilities (validation, clock matching, execution control). ```go // TriggerType enum type TriggerType string const ( TriggerClock TriggerType = "clock" TriggerHuman TriggerType = "human" TriggerEvent TriggerType = "event" ) // Manager handles all trigger types: // - Clock: Manager.Tick() called by internal ticker // - Human: Manager.Intervene() called by API // - Event: Manager.HandleEvent() called by webhook/db trigger // trigger/ package provides utilities: // - trigger.ValidateIntervention(req) - validate human intervention request // - trigger.ValidateEvent(req) - validate event request // - trigger.BuildEventInput(req) - build TriggerInput from event // - trigger.ClockMatcher - reusable clock matching logic // - trigger.ExecutionController - pause/resume/stop execution type InterveneRequest struct { TeamID string MemberID string Action InterventionAction // task.add | goal.adjust | task.cancel | plan.add | instruct Messages []context.Message // user input (text, images, files) PlanTime *time.Time // for action=plan.add ExecutorMode ExecutorMode // optional: standard | dryrun (override robot config) } type EventRequest struct { MemberID string Source string // webhook path or table name EventType string // lead.created, etc. Data map[string]interface{} ExecutorMode ExecutorMode // optional: standard | dryrun (override robot config) } type ExecutionResult struct { ExecutionID string // Job execution ID Status ExecStatus // pending | running | completed | failed Message string // status message } type RobotState struct { MemberID string // member_id from __yao.member Status RobotStatus // idle | working | paused | error | maintenance LastRun time.Time NextRun time.Time Running int // current running execution count MaxRunning int // max concurrent executions (from Quota.Max) RunningIDs []string // list of running execution IDs } ``` ### 8.3 Execution (Uses ExecutionStore) Uses dedicated `__yao.agent_execution` table via ExecutionStore. **Each trigger creates a new Execution:** ```go // On each trigger (clock/human/event), create a new Execution exec := &types.Execution{ ID: utils.NewID(), MemberID: memberID, TeamID: teamID, TriggerType: triggerType, Status: types.ExecStatusRunning, Phase: types.PhaseP0Init, StartedAt: time.Now(), } // Save to ExecutionStore execStore.Save(exec) ``` **Query executions for a robot:** ```go // List all executions for a robot member executions, err := execStore.List(memberID, 1, 10) ``` **Query examples:** ```go // Get execution by ID exec, err := execStore.Get(executionID) // List executions for a robot executions, err := execStore.List(memberID, page, pageSize) // Update execution status execStore.UpdateStatus(executionID, types.ExecStatusCompleted) // Logging via kun/log log.With(log.F{"execution_id": exec.ID, "phase": "P1"}).Info("Phase started") ``` --- ## 9. Security 1. **Team only**: Agent sees only its team's data 2. **Role rules**: Uses role_id permissions 3. **Limited tools**: Only what's in `resources` 4. **Timeout**: Stops if runs too long 5. **Logs**: All runs saved --- ## 10. Quick Ref ### Triggers ```yaml triggers: clock: { enabled: true } intervene: { enabled: true, actions: [...] } event: { enabled: false } ``` ### Clock ```yaml # Mode 1: Specific times clock: mode: times times: ["09:00", "14:00", "17:00"] days: ["Mon", "Tue", "Wed", "Thu", "Fri"] tz: Asia/Shanghai timeout: 30m # Mode 2: Interval clock: mode: interval every: 30m # run every 30 minutes timeout: 10m # Mode 3: Daemon (continuous thinking/analysis) clock: mode: daemon # restart immediately after each run timeout: 10m # max time per run # Use case: Research analyst, market monitor ``` ### Phase Agents ```yaml # Optional - defaults to __yao.{phase} if not specified resources: phases: inspiration: "__yao.inspiration" # Clock only goals: "__yao.goals" tasks: "__yao.tasks" validation: "__yao.validation" delivery: "__yao.delivery" learning: "__yao.learning" ``` ### Quota ```yaml quota: max: 2 # max running queue: 10 # queue size priority: 5 # 1-10 ``` ### Executor ```yaml # Standard mode (default) - real Agent calls executor: mode: standard max_duration: 30m # DryRun mode - simulated execution (for testing/demos) executor: mode: dryrun # Sandbox mode (NOT IMPLEMENTED) - container-isolated # Requires Docker/gVisor infrastructure # executor: # mode: sandbox # max_duration: 10m ``` **API Override:** ```javascript // Override executor mode per trigger const result = Process("robot.Trigger", "mem_abc123", { type: "human", action: "task.add", messages: [{ role: "user", content: "Test task" }], executor_mode: "dryrun", // override robot config }); ``` --- ## 11. Examples Each example shows a different trigger mode: | Example | Trigger | Mode | Scenario | | ------- | ------- | --------- | -------------------------------------------- | | 11.1 | Clock | times | SEO/GEO Content - daily content optimization | | 11.2 | Clock | interval | Competitor Monitor - check every 2 hours | | 11.3 | Clock | daemon | Research Analyst - continuous insight mining | | 11.4 | Human | intervene | Sales Assistant - manager assigns tasks | | 11.5 | Event | webhook | Lead Processor - qualify and route new leads | --- ### 11.1 SEO/GEO Content Agent (Clock: times) **Trigger:** Clock - specific times daily **Role:** AI Marketing - auto-generate and optimize SEO/GEO content. ```json // robot_config for SEO Content Agent { "triggers": { "clock": { "enabled": true }, "intervene": { "enabled": true } }, "clock": { "mode": "times", "times": ["06:00", "18:00"], "days": ["Mon", "Tue", "Wed", "Thu", "Fri"], "tz": "Asia/Shanghai" }, "identity": { "role": "SEO/GEO Content Specialist", "duties": [ "Research trending keywords in our industry", "Generate SEO-optimized articles (2-3 per day)", "Optimize existing content for GEO (AI search)", "Track keyword rankings and adjust strategy", "A/B test titles and meta descriptions" ] }, "resources": { "agents": ["keyword-researcher", "content-writer", "seo-optimizer"], "mcp": [ { "id": "google-search", "tools": ["trends", "rankings"] }, { "id": "cms", "tools": ["create", "update", "publish"] } ] }, "delivery": { "type": "notify", "opts": { "channel": "marketing-team" } } } ``` **Example run at 06:00 Monday:** ``` P0 Inspiration: Clock: Monday 06:00, start of week Data: - Keyword "AI app development" trending (+45% this week) - Our article ranks #8, competitor #2 - 3 articles need GEO optimization World: New AI regulation announced last Friday P1 Goals: 1. Write new article targeting "AI app development" 2. Optimize 3 old articles for GEO 3. Update meta descriptions for top 5 pages P2 Tasks: 1. Research "AI app development" keywords β†’ keyword-researcher 2. Write article with SEO structure β†’ content-writer 3. Add FAQ schema for GEO β†’ seo-optimizer 4. Publish to CMS β†’ cms.publish P3 Execute: - Keywords: "AI app development", "build AI apps", "AI dev guide" (12 total) - Article: 2500 words, 8 sections, FAQ schema added - Published to CMS, indexed by Google P4 Delivery: β†’ Notify: "Published: 'Complete Guide to AI App Development' - targeting 12 keywords" P5 Learn: - "AI app development" articles perform well on Monday morning - FAQ schema improves GEO visibility by 30% ``` --- ### 11.2 Competitor Monitor (Clock: interval) **Trigger:** Clock - every 2 hours **Role:** Monitor competitors, track market changes, alert on important updates. ```json // robot_config for Competitor Monitor { "triggers": { "clock": { "enabled": true } }, "clock": { "mode": "interval", "every": "2h" }, "identity": { "role": "Competitor Intelligence Analyst", "duties": [ "Monitor competitor websites for changes", "Track competitor pricing updates", "Watch for new product launches", "Analyze competitor content strategy", "Alert team on significant changes" ] }, "resources": { "agents": ["web-scraper", "diff-analyzer", "report-writer"], "mcp": [{ "id": "web-search", "tools": ["search", "news"] }] }, "delivery": { "type": "webhook", "opts": { "url": "https://slack.com/webhook/competitor-alerts" } } } ``` **Example run detecting competitor change:** ``` P0 Inspiration: Clock: Tuesday 14:00 Data: - Competitor A: pricing page changed - Competitor B: new blog post about "AI agents" - Competitor C: no changes P1 Goals: 1. Analyze Competitor A pricing change 2. Summarize Competitor B's new content 3. Assess impact on our positioning P2 Tasks: 1. Scrape old vs new pricing β†’ web-scraper 2. Compare pricing tiers β†’ diff-analyzer 3. Generate competitive analysis β†’ report-writer P3 Execute: - Competitor A: dropped price 20% on enterprise tier - Competitor B: targeting same keywords as us P4 Delivery: β†’ Slack: "🚨 Competitor A cut enterprise price 20% - review needed" P5 Learn: - Competitor A tends to change pricing on Tuesdays - Price changes often precede feature launches ``` --- ### 11.3 Industry Research Analyst (Clock: daemon) **Trigger:** Clock - continuous daemon mode **Role:** Continuously read industry news, papers, social media; extract insights; build knowledge. ```json // robot_config for Research Analyst { "triggers": { "clock": { "enabled": true } }, "clock": { "mode": "daemon", "timeout": "10m" }, "identity": { "role": "Industry Research Analyst", "duties": [ "Continuously scan industry news and papers", "Analyze trends and extract key insights", "Identify emerging technologies and competitors", "Build and maintain industry knowledge base", "Alert team on significant developments" ] }, "resources": { "agents": ["content-reader", "insight-extractor", "report-writer"], "mcp": [ { "id": "web-search", "tools": ["search", "news"] }, { "id": "arxiv", "tools": ["search", "fetch"] }, { "id": "twitter", "tools": ["search", "trends"] } ] }, "delivery": { "type": "notify", "opts": { "channel": "research-insights" } } } ``` **Example continuous run:** ``` Run #1 (09:00): P0: Scan sources - 15 new AI news articles - 3 new papers on arXiv - Twitter: "AI Agent" trending P1: Goals: 1. Read and analyze new content 2. Extract insights relevant to our business 3. Update knowledge base P2: Tasks: 1. Read articles β†’ content-reader 2. Analyze papers β†’ content-reader 3. Extract insights β†’ insight-extractor P3: Execute: - Article: "OpenAI releases new agent framework" Insight: Validates our direction, watch for API changes - Paper: "Multi-agent collaboration patterns" Insight: Useful for our agent design, save to KB - Twitter: Sentiment positive on AI agents P4: Notify: "πŸ“š 3 new insights added to KB" P5: Learn: OpenAI news = high relevance, prioritize β†’ Restart immediately Run #2 (09:12): P0: Scan sources - 2 new articles (low relevance) - No new papers - Twitter: Normal activity P1: Low-value content, skip deep analysis P5: Learn: Mid-morning usually quiet β†’ Restart immediately Run #3 (09:25): P0: Scan sources - Breaking: "Competitor X raises $100M for AI platform" P1: Goals: 1. Deep analyze competitor news 2. Assess impact on our market 3. Alert team immediately P2: Tasks: 1. Gather all competitor X info β†’ web-search 2. Analyze their positioning β†’ insight-extractor 3. Write competitive brief β†’ report-writer P3: Execute: - Competitor X: Focus on enterprise, similar target market - Funding: Will likely expand sales team - Threat level: Medium-High P4: Notify: "🚨 Competitor X raised $100M - brief attached" P5: Learn: Funding news = always high priority β†’ Restart immediately ``` --- ### 11.4 Sales Assistant (Human: intervene) **Trigger:** Human intervention - sales manager assigns tasks **Role:** Help sales team with research, proposals, follow-ups when manager assigns work. ```json // robot_config for Sales Assistant { "triggers": { "clock": { "enabled": false }, "intervene": { "enabled": true, "actions": ["task.add", "goal.adjust", "instruct"] } }, "identity": { "role": "Sales Assistant", "duties": [ "Research assigned prospects and companies", "Prepare customized proposals and presentations", "Draft follow-up emails", "Analyze deal history and suggest strategies", "Prepare meeting briefs" ] }, "resources": { "agents": ["company-researcher", "proposal-writer", "email-drafter"], "mcp": [ { "id": "crm", "tools": ["query", "update"] }, { "id": "linkedin", "tools": ["search", "profile"] }, { "id": "email", "tools": ["draft", "send"] } ] }, "delivery": { "type": "email", "opts": { "to": ["sales-manager@company.com"] } } } ``` **Example: Sales manager assigns task:** ``` Sales Manager Input: Action: task.add Messages: [{ role: "user", content: "Meeting with BigCorp CTO tomorrow. Prepare materials. They do smart manufacturing, $150M revenue, digital transformation." }] Agent Execution (no P0 for human trigger): P1 Goals (from human input): 1. Research BigCorp and their CTO 2. Prepare meeting brief 3. Draft customized proposal P2 Tasks: 1. Research BigCorp β†’ company-researcher - Company background, recent news - Digital transformation status - Potential pain points 2. Research CTO profile β†’ linkedin.profile - Background, interests - Recent posts/articles 3. Prepare meeting brief β†’ proposal-writer 4. Draft proposal β†’ proposal-writer P3 Execute: - BigCorp: Leading smart manufacturing, 3 factories, implementing MES - CTO John: Ex-Google, focused on AI+Manufacturing, recent post on "AI QC" - Pain point: High QC labor cost, 2% defect miss rate - Opportunity: Our AI QC solution can reduce miss rate to 0.1% P4 Delivery: β†’ Email to sales manager: - Attachment 1: BigCorp Research Report (PDF) - Attachment 2: CTO Profile Brief - Attachment 3: Custom Proposal - AI QC Solution - Attachment 4: Meeting Agenda Suggestion Sales Manager Follow-up: Action: task.add Messages: [{ role: "user", content: "Also prepare some similar case studies, manufacturing preferred" }] Agent Continues: P1: Find similar manufacturing case studies P2: Search CRM for manufacturing wins P3: Found 3 cases: Auto parts factory, Electronics plant, Food processing P4: Email: "3 manufacturing case studies attached" P5: Learn: Manufacturing prospects often need QC case studies ``` --- ### 11.5 Lead Processor (Event: webhook) **Trigger:** Event - new lead from website/CRM **Role:** Instantly process and qualify new leads, route to sales. ```json // robot_config for Lead Processor { "triggers": { "clock": { "enabled": false }, "event": { "enabled": true } }, "events": [ { "type": "webhook", "source": "/webhook/leads", "filter": { "event_types": ["lead.created"] } }, { "type": "database", "source": "crm_leads", "filter": { "trigger": "insert" } } ], "identity": { "role": "Lead Qualification Specialist", "duties": [ "Instantly process new leads", "Enrich lead data (company info, LinkedIn)", "Score lead quality (1-100)", "Route hot leads to sales immediately", "Add cold leads to nurture sequence" ] }, "resources": { "agents": ["data-enricher", "lead-scorer"], "mcp": [ { "id": "clearbit", "tools": ["enrich"] }, { "id": "crm", "tools": ["update", "assign"] }, { "id": "email", "tools": ["send"] } ] }, "delivery": { "type": "webhook", "opts": { "url": "https://slack.com/webhook/sales-leads" } } } ``` **Example: New lead event:** ``` Event Received: Type: lead.created Data: { name: "John Smith", email: "john@bigcorp.com", company: "BigCorp", message: "Interested in Enterprise pricing, team of 50" } Agent Execution (no P0 for events): P1 Goals: 1. Enrich lead data 2. Score lead quality 3. Route appropriately P2 Tasks: 1. Lookup company info β†’ clearbit.enrich 2. Calculate lead score β†’ lead-scorer 3. Update CRM β†’ crm.update 4. Notify sales β†’ slack webhook P3 Execute: - Company: BigCorp, 500 employees, Series C - LinkedIn: VP of Engineering - Lead Score: 85/100 (HOT) - Reason: Enterprise inquiry, decision maker, funded company P4 Delivery: β†’ Slack: "πŸ”₯ HOT LEAD (85/100): John Smith @ BigCorp - 500 employees, Series C - Interested in Enterprise (50 seats) - Assigned to: Sales Rep A" β†’ CRM: Lead updated, assigned to Sales Rep A β†’ Email to lead: "Thanks for your inquiry. Our sales rep will contact you within 1 hour." P5 Learn: - BigCorp profile saved for future reference - VP-level leads from funded companies = high conversion ```