# 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 ```mermaid flowchart TB subgraph Triggers["Triggers"] WC[/"⏰ Clock"/] HI[/"πŸ‘€ Human"/] EV[/"πŸ“‘ Event"/] end subgraph Manager["Manager"] 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")] Job[("Job")] 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 & Job KB -.->|History| P0 ``` ### 2.2 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 | | `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 | | --------- | ----------------------------- | -------------------- | | **Clock** | Timer (times/interval/daemon) | `triggers.clock` | | **Human** | Manual action | `triggers.intervene` | | **Event** | Webhook, DB change | `triggers.event` | All on by default. Turn off per agent: ```yaml triggers: clock: { enabled: true } intervene: { enabled: true, actions: ["add_task", "pause"] } 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 | Validator | Results | Checked results | Always | | P4 | Delivery | All results | Email/File | 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). ``` 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. ``` ### 4.4 P2: Tasks P2 Agent reads Goals markdown and breaks into executable tasks: ```go type Task struct { ID string // unique task ID 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 } ``` ### 4.5 P3: Run For each task: 1. Call Assistant or MCP Tool 2. Get result 3. Validate 4. Update status ### 4.6 P4: Deliver Send output: ```yaml delivery: type: email # email | file | webhook | notify opts: to: ["manager@company.com"] ``` ### 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 *Delivery `json:"delivery"` Events []Event `json:"events,omitempty"` } ``` ### 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 PhaseValidation Phase = "validation" // P3 PhaseDelivery Phase = "delivery" // P4 PhaseLearning Phase = "learning" // P5 ) // AllPhases for iteration var AllPhases = []Phase{ PhaseInspiration, PhaseGoals, PhaseTasks, PhaseValidation, 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" DeliveryFile DeliveryType = "file" DeliveryWebhook DeliveryType = "webhook" DeliveryNotify DeliveryType = "notify" ) // ExecStatus - execution status enum type ExecStatus string const ( ExecPending ExecStatus = "pending" ExecRunning ExecStatus = "running" ExecCompleted ExecStatus = "completed" ExecFailed ExecStatus = "failed" ) // 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 } // Delivery type Delivery struct { Type DeliveryType `json:"type"` Opts map[string]interface{} `json:"opts"` } // 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"] } } }, "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. Create Job 6. Set active ### 6.3 On Delete 1. Stop running jobs 2. Remove from cache 3. Delete Job 4. 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 Job System **Relationship:** 1 Robot : N Executions (concurrent), 1 Execution = 1 job.Job Each trigger creates a new Execution, mapped to a `job.Job` for monitoring. ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Activity Monitor (UI) β”‚ β”‚ β€’ List jobs β”‚ β”‚ β€’ See progress β”‚ β”‚ β€’ View logs β”‚ β”‚ β€’ Cancel/retry β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Job Framework β”‚ β”‚ Job β†’ Execution β†’ Progress β†’ Logs β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` **Go APIs (yao/job package):** | Action | API | | ------------ | -------------------------------------------------------- | | List Jobs | `job.ListJobs(param, page, pagesize)` | | Get Job | `job.GetJob(jobID, param)` | | Save Job | `job.SaveJob(j)` | | 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:** - `adjust_goal`: Change goal - `add_task`: Add task - `cancel_task`: Stop task - `pause` / `resume` / `abort` - `plan`: Do later **Plan Queue:** - Holds tasks for later - Runs at next cycle start --- ## 8. API ### 8.1 Manager (Internal) ```go type Manager interface { // Lifecycle Start() error Stop() error // Cache LoadActiveRobots(ctx context.Context) error GetRobot(teamID, memberID string) *Robot // Clock trigger (internal, called by ticker) Tick(ctx context.Context, now time.Time) error } ``` ### 8.2 Trigger (Called by openapi layer) ```go // TriggerType enum type TriggerType string const ( TriggerClock TriggerType = "clock" TriggerHuman TriggerType = "human" TriggerEvent TriggerType = "event" ) // Trigger interface - called by openapi handlers type Trigger interface { // Human intervention Intervene(ctx context.Context, req InterveneRequest) (*ExecutionResult, error) // Event trigger (webhook, db change) HandleEvent(ctx context.Context, req EventRequest) (*ExecutionResult, error) // Query & control GetStatus(ctx context.Context, teamID, memberID string) (*RobotState, error) Pause(ctx context.Context, teamID, memberID string) error Resume(ctx context.Context, teamID, memberID string) error } type InterveneRequest struct { TeamID string MemberID string Action string // add_task | adjust_goal | cancel_task | pause | resume | abort | plan Description string Priority string // high | normal | low PlanTime time.Time // for action=plan } type EventRequest struct { MemberID string Source string // webhook path or table name EventType string // lead.created, etc. Data map[string]interface{} } type ExecutionResult struct { ExecutionID string // Job execution ID Status ExecStatus // pending | running | completed | failed } 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 Job System) No separate `autonomous_executions` table. Uses existing Job system. **Each trigger creates a new job.Job:** ```go // On each trigger (clock/human/event), create a new Job execID := gonanoid.Must() j, _ := job.Once(job.GOROUTINE, map[string]interface{}{ "job_id": "robot_exec_" + execID, // unique per execution "category_id": "autonomous_robot", "name": fmt.Sprintf("%s - %s", member.DisplayName, triggerType), "metadata": map[string]interface{}{ "member_id": memberID, "team_id": teamID, "trigger_type": triggerType, "exec_id": execID, }, }) job.SaveJob(j) // Configure and start j.ExecutionConfig = &job.ExecutionConfig{ Type: job.ExecutionTypeProcess, ProcessName: "robot.Execute", ProcessArgs: []interface{}{memberID, execID, triggerData}, } j.Push() ``` **Query executions for a robot:** ```go // List all executions for a robot member param := model.QueryParam{ Wheres: []model.QueryWhere{ {Column: "category_id", Value: "autonomous_robot"}, {Column: "metadata->member_id", Value: memberID}, }, Orders: []model.QueryOrder{{Column: "created_at", Option: "desc"}}, } jobs, _ := job.ListJobs(param, 1, 10) ``` **Query examples:** ```go // List all robot jobs (all robots, all executions) param := model.QueryParam{ Wheres: []model.QueryWhere{ {Column: "category_id", Value: "autonomous_robot"}, }, } jobs, _ := job.ListJobs(param, 1, 20) // Get executions for a robot execParam := model.QueryParam{ Wheres: []model.QueryWhere{ {Column: "job_id", Value: "robot_" + memberID}, }, Orders: []model.QueryOrder{{Column: "created_at", Option: "desc"}}, } execs, _ := job.ListExecutions(execParam, 1, 10) // Get logs for an execution logParam := model.QueryParam{ Wheres: []model.QueryWhere{ {Column: "execution_id", Value: execID}, }, } logs, _ := job.ListLogs(logParam, 1, 100) ``` --- ## 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 ``` --- ## 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": ["add_task", "adjust_goal", "pause"] } }, "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: add_task Description: "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: add_task Description: "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 ```