- Introduced a new `Description` field in the `Task` struct for a human-readable task description, improving UI clarity. - Updated the `ParseTask` function to save the description from input data and convert it to a message if no explicit messages are provided. - Enhanced the `Executor` to update UI fields with localized messages during task execution phases, ensuring better user feedback. - Implemented a new method in the `ExecutionStore` to persist task status updates, allowing real-time UI updates. - Added unit tests to validate the new task description handling and UI updates during execution phases.
44 KiB
Robot OpenAPI - Implementation TODO
Based on:
openapi/agent/robot/DESIGN.md,openapi/agent/robot/GAPS.mdDepends on:yao/agent/robot/api/(Go API layer) Base Path:/v1/agent/robots
Field Alignment Review Summary
Last reviewed: 2026-01-23
Robot Fields ✅ Fully Aligned
Backend (types.go) |
Frontend (types.ts) |
Status |
|---|---|---|
member_id |
member_id |
✅ |
team_id |
team_id |
✅ |
display_name |
display_name |
✅ |
bio |
bio / description |
✅ |
name (← member_id) |
name |
✅ |
description (← bio) |
description |
✅ |
robot_status |
robot_status |
✅ |
autonomous_mode |
autonomous_mode |
✅ |
robot_config |
robot_config |
✅ |
robot_email |
robot_email |
✅ |
| All other fields | Same | ✅ |
Execution Fields ✅ Aligned
Backend (types.go) |
Frontend (types.ts) |
Status |
|---|---|---|
id |
id |
✅ Aligned |
member_id |
member_id |
✅ |
team_id |
team_id |
✅ |
trigger_type |
trigger_type |
✅ |
status |
status |
✅ |
phase |
phase |
✅ |
start_time |
start_time |
✅ |
end_time |
end_time |
✅ |
error |
error |
✅ |
input |
input |
✅ Optional |
| Phase outputs | Same | ✅ Detail view |
name |
name |
✅ Added |
current_task_name |
current_task_name |
✅ Added |
| - | job_id |
🗑️ Dead field, to be removed |
Task Fields ✅ Aligned
Backend (types.go) |
Frontend (types.ts) |
Status |
|---|---|---|
id |
id |
✅ |
description |
description |
✅ Added |
goal_ref |
goal_ref |
✅ |
source |
source |
✅ |
executor_type |
executor_type |
✅ |
executor_id |
executor_id |
✅ |
status |
status |
✅ |
order |
order |
✅ |
start_time |
start_time |
✅ |
end_time |
end_time |
✅ |
Action Items:
- Backend:
Executionstruct - addName,CurrentTaskNamefields (see Improvement Plan below) - Backend:
RobotConfigstruct - addDefaultLocalefield (see Improvement Plan below) - Backend:
TriggerInputstruct - addLocalefield (see Improvement Plan below) - Backend: Database model
execution.mod.yao- addname,current_task_namecolumns - Backend: Executor - update
Name,CurrentTaskNameat each phase - Backend: Store layer - add
UpdateUIFields()method - Backend: Unit tests for UI fields and i18n (executor/standard/ui_fields_test.go, store/execution_test.go)
- Backend:
Taskstruct - addDescriptionfield for human-readable task description - Backend:
ParseTask()- save description from LLM output toTask.Description - Frontend:
Tasktype - adddescriptionfield - Frontend: Task list display - use
descriptionas primary title, fallback toexecutor_id - Frontend: Remove
job_idfield fromtypes.ts - Frontend: Remove
job_idmock data frommock/data.ts - Frontend: Use
nameandcurrent_task_namedirectly from API response
Improvement Plan: Execution UI Display Fields ✅ Implemented
Problem: Frontend needs to display "execution title" and "current task", which must be dynamically updated at different phases Solution: Backend manages these fields centrally;
Executionstruct gets new fields, executor updates them at each phase
1. Execution struct fields (agent/robot/types/robot.go): ✅
type Execution struct {
// ... existing fields ...
// UI display fields (updated by executor at each phase)
Name string `json:"name,omitempty"` // Execution title
CurrentTaskName string `json:"current_task_name,omitempty"` // Current task description
}
2. Update timeline: ✅
| Phase | Name |
CurrentTaskName |
|---|---|---|
| Created | Human: extract from input.messages[0]Clock/Event: "Preparing..." (localized) |
"Starting..." (localized) |
inspiration |
- | "Analyzing context..." (localized) |
goals complete |
Extract first line from goals.content |
"Planning goals..." (localized) |
tasks |
- | "Breaking down tasks..." (localized) |
run (each task) |
- | Current task description (e.g., "Task 1/3: ...") |
| Completed/Failed | - | "Completed" / "Failed: {error}" (localized) |
3. Implementation files:
agent/robot/types/robot.go- Execution struct fields ✅agent/robot/store/execution.go- UpdateUIFields() method ✅agent/robot/executor/standard/executor.go- initUIFields(), updateUIFields(), i18n messages ✅agent/robot/executor/standard/inspiration.go- Update CurrentTaskName ✅agent/robot/executor/standard/goals.go- Update Name and CurrentTaskName ✅agent/robot/executor/standard/tasks.go- Update CurrentTaskName ✅agent/robot/executor/standard/run.go- Update CurrentTaskName for each task ✅yao/models/agent/execution.mod.yao- Database columns ✅
Improvement Plan: i18n Default Locale ✅ Implemented
Problem: Clock/Event triggers have no user context, unknown which language to use for generated content Solution:
RobotConfiggets a default locale configuration field
1. RobotConfig struct field (agent/robot/types/config.go): ✅
type Config struct {
// ... existing fields ...
DefaultLocale string `json:"default_locale,omitempty"` // "en" | "zh", default "en"
}
// GetDefaultLocale returns the default locale (default: "en")
func (c *Config) GetDefaultLocale() string {
if c == nil || c.DefaultLocale == "" {
return "en"
}
return c.DefaultLocale
}
2. TriggerInput struct field (agent/robot/types/robot.go): ✅
type TriggerInput struct {
// ... existing fields ...
Locale string `json:"locale,omitempty"` // Language from human trigger
}
3. Locale determination logic (agent/robot/executor/standard/executor.go): ✅
func getEffectiveLocale(robot *Robot, input *TriggerInput) string {
// 1. Human trigger: use locale from request
if input != nil && input.Locale != "" {
return input.Locale
}
// 2. Clock/Event trigger: use Robot config
if robot != nil && robot.Config != nil {
return robot.Config.GetDefaultLocale()
}
// 3. System default
return "en"
}
4. Locale source priority: ✅
| Trigger Type | Locale Source |
|---|---|
| Human | Request locale → Robot default_locale → "en" |
| Event | Robot default_locale → "en" |
| Clock | Robot default_locale → "en" |
5. Localized messages (executor.go): ✅
var uiMessages = map[string]map[string]string{
"en": {
"preparing": "Preparing...",
"starting": "Starting...",
"scheduled_execution": "Scheduled execution",
"event_prefix": "Event: ",
"event_triggered": "Event triggered",
"analyzing_context": "Analyzing context...",
"planning_goals": "Planning goals...",
"breaking_down_tasks": "Breaking down tasks...",
"completed": "Completed",
"failed_prefix": "Failed: ",
"task_prefix": "Task",
},
"zh": {
"preparing": "准备中...",
"starting": "启动中...",
"scheduled_execution": "定时执行",
// ... more Chinese messages
},
}
Note: User preference locale fallback deferred to future version
Deferred Features (Phase 5/6)
| Feature | Current Status | Future Plan |
|---|---|---|
| Trigger/Intervene UI | Backend done, frontend deferred | Phase 5 (requires SSE) |
| Real-time refresh | Polling 60s | Phase 6 (SSE streams) |
| Multi-turn chat | Not started | Phase 5 |
Implementation Strategy
Integrate frontend immediately after each phase to validate deliverables. Frontend has fallback mechanisms (polling, single-submit mode).
🟢 Phase 1: Core CRUD ✅
Backend → SDK → Page Integration
└─ List, Get, Create, Update, Delete robots
✅ Phase 1-FE: Frontend Integration ✅ [Completed]
└─ SDK (openapi/robot.ts) ✅
└─ Page Integration (Robot list, detail, create, edit, delete) ✅
└─ UI/UX (CreatureLoading, bubble animations) ✅
✅ Phase 1.5: Robot Manager Lifecycle ✅ [Completed]
└─ Auto-start Manager on Yao startup (async)
└─ Auto-reload cache on robot update
└─ Auto-remove from cache on robot delete
└─ Graceful shutdown on Yao unload
└─ Lazy-load for non-autonomous robots (load on trigger, unload after execution)
└─ Unit tests: TestManagerLazyLoadNonAutonomous (6 test cases)
🟢 Phase 2: Execution Management
Backend → SDK → Page Integration
└─ List, Get, Control executions, Trigger/Intervene
🟢 Phase 3: Results & Activities
Backend → SDK → Page Integration
└─ List deliverables, Activity feed
🟢 Phase 4: i18n
Backend → SDK → Page Integration
└─ Locale parameter support
🟡 Medium Risk (Deferred):
Phase 5: Multi-turn Chat API + Trigger/Intervene UI
Phase 6: Real-time SSE Streams (replace polling)
🟢 Phase 1: Core CRUD ✅ [Low Risk]
Goal: Basic robot management endpoints Risk: 🟢 Low - All new code, no changes to existing logic Status: ✅ Backend Complete → Proceed to Phase 1.5 Frontend Integration
1.1 Backend Prerequisites ✅
Types & Cache
- Add
Biofield totypes.Robotstruct inyao/agent/robot/types/robot.go - Add
biotomemberFieldsinyao/agent/robot/cache/load.go
Store Layer (Core CRUD - implement first)
- Create
store/robot.gowithRobotStorestruct - Implement
RobotStore.Save()- create/update robot member - Implement
RobotStore.Get()- get by member_id - Implement
RobotStore.List()- list with filters - Implement
RobotStore.Delete()- delete robot member - Implement
RobotStore.UpdateConfig()- update config only - Implement
RobotStore.UpdateStatus()- update status only - Add Yao permission fields support (
__yao_created_by,__yao_team_id, etc.) - Add tests:
store/robot_test.go
API Layer (Thin wrappers calling store)
- Implement
api.CreateRobot()- callstore.RobotStore.Save()+ cache refresh- Auto-generate
member_idif not provided (12-digit numeric, matches existing pattern)
- Auto-generate
- Implement
api.UpdateRobot()- partial update + cache refresh - Implement
api.RemoveRobot()- callstore.RobotStore.Delete()+ cache invalidate - Implement
api.GetRobotResponse()- get robot as API response - Add
AuthScopefor Yao permission fields - Add request/response types in
api/types.go - Add tests:
api/robot_test.go
Utils Layer
- Create
utils/convert.gowith unified type conversion functions - Implement
To<Type>functions (ToBool, ToInt, ToFloat64, ToTimestamp, ToJSONValue) - Implement
Get<Type>functions for map value extraction - Add tests:
utils/convert_test.go
1.2 OpenAPI Setup ✅
- Create
openapi/agent/robot/directory (sub-package under agent) - Create
robot.go- route registration withAttach()function - Register routes in
openapi/agent/agent.goviarobot.Attach(group.Group("/robots"), oauth) - Add OAuth guard middleware
1.3 OpenAPI Types ✅
Note: Core types already exist in
agent/robot/api/types.go. OpenAPI layer needs HTTP-specific types.
types.go- HTTP request/response typesRobotResponsestruct (with field mapping:name←member_id,description←bio)RobotStatusResponsestructListRobotsResponsestructCreateRobotRequeststruct (HTTP binding)UpdateRobotRequeststruct (HTTP binding)NewRobotResponse()- conversion fromapi.RobotResponseNewRobotStatusResponse()- conversion fromapi.RobotState
1.4 List Robots ✅
list.go- GET /v1/agent/robots- Parse query params:
status,keywords,page,pagesize,team_id - Call
robot/api.ListRobots() - Team constraint from auth info
- Test:
tests/agent/robot_test.go#TestListRobots
1.5 Get Robot ✅
detail.go- GET /v1/agent/robots/:id- Parse path param
- Call
robot/api.GetRobotResponse() - Team access check
- Test:
tests/agent/robot_test.go#TestGetRobot
1.6 Create Robot ✅
- POST /v1/agent/robots handler
- Parse HTTP request to
CreateRobotRequest - Auto-generate
member_idif not provided (12-digit numeric, consistent with existing API) - Apply
AuthScopewith permission fields (CreatedBy, TeamID, TenantID) - Call
robot/api.CreateRobot() - Return created robot (201 Created)
- Handle duplicate (409 Conflict)
- Test:
tests/agent/robot_test.go#TestCreateRobot
1.7 Update Robot ✅
- PUT /v1/agent/robots/:id handler
- Parse HTTP request to
UpdateRobotRequest - Team permission check
- Apply
AuthScopewith UpdatedBy - Call
robot/api.UpdateRobot() - Return updated robot
- Test:
tests/agent/robot_test.go#TestUpdateRobot
1.8 Delete Robot ✅
- DELETE /v1/agent/robots/:id handler
- Team permission check
- Call
robot/api.RemoveRobot() - Handle running executions (409 Conflict)
- Return success response
- Test:
tests/agent/robot_test.go#TestDeleteRobot
1.9 Status Endpoint ✅
- GET /v1/agent/robots/:id/status handler
- Call
robot/api.GetRobotStatus() - Return runtime status (running count, max, last/next run)
- Test:
tests/agent/robot_test.go#TestGetRobotStatus
1.10 Utilities ✅
utils.go- helper functionsGetLocale(c *gin.Context)- extract locale from query/headerParseBoolValue()- parse bool from string
1.11 Permission Logic ✅
permission.go- permission check functionsCanRead()- read permission check (creator or team member)CanWrite()- write permission check (creator only)GetEffectiveTeamID()- get effective team_id (user_id for personal users)BuildListFilter()- build list filter based on permissions
- Apply permission checks in handlers:
GetRobot- checkCanRead()withYaoTeamIDandYaoCreatedByGetRobotStatus- checkCanRead()UpdateRobot- checkCanWrite()DeleteRobot- checkCanWrite()ListRobots- useBuildListFilter()for team filteringCreateRobot- auto-set__yao_team_idtouser_idfor personal users
- Add Yao permission fields to API layer:
api/types.go- addYaoCreatedBy,YaoTeamIDtoRobotResponseandRobotStateapi/robot.go- populate permission fields inrecordToResponse()andGetRobotStatus()store/robot.go- add__yao_*fields torobotFields
- Permission tests in
tests/agent/robot_test.go#TestRobotPermissions
✅ Phase 1-FE: Frontend Integration ✅ [Completed]
Goal: Implement frontend SDK and integrate pages to validate Phase 1 deliverables Status: ✅ Completed
1-FE.1 SDK Implementation ✅
Location:
cui/packages/cui/openapi/agent/robot/
- Create
robot/types.ts- TypeScript types for Robot APIRobotFilter- filter options for listing (includingautonomous_mode)Robot- robot data structureRobotStatusResponse- runtime statusRobotCreateRequest/RobotUpdateRequest- CRUD requestsRobotDeleteResponse- delete response
- Create
robot/robots.ts- Robot API SDK class (AgentRobots)List(filter)- GET /v1/agent/robotsGet(id)- GET /v1/agent/robots/:idGetStatus(id)- GET /v1/agent/robots/:id/statusCreate(data)- POST /v1/agent/robotsUpdate(id, data)- PUT /v1/agent/robots/:idDelete(id)- DELETE /v1/agent/robots/:id
- Create
robot/index.ts- exports - Update
agent/api.ts- addrobotsproperty to Agent class - Update
agent/index.ts- export robot module - Linter check passed
1-FE.2 Page Integration ✅
Location:
cui/packages/cui/pages/mission-control/
- Create
useRobotshook for API callslistRobots(filter)- list robots with paginationgetRobot(id)- get single robotgetRobotStatus(id)- get runtime statuscreateRobot(data)- create robotupdateRobot(id, data)- update robotdeleteRobot(id)- delete robot- Error handling and loading state
- Robot List Page (
mission-control/index.tsx)- Replace mock data with
listRobots()API (fallback to mock) - Fetch status for each robot via
getRobotStatus() - Refresh list after robot created/updated/deleted
- Empty state with "Create Agent" button (with bubble animation)
- Implement pagination (TODO: Phase 2)
- Implement filters (status, keywords, team) (TODO: Phase 2)
- Replace mock data with
- Robot Detail Modal (
AgentModal)- Real-time status refresh via
getRobotStatus(id) - Auto-refresh every 10 seconds while modal open
- Merge real-time status with robot data
- Real-time status refresh via
- Create Robot (
AddAgentModal)- Call
createRobot()API - Handle success/error messages
- Form validation (existing)
- Load email domains, managers, agents, MCP servers from API
- Call
- Edit Robot (
ConfigTabinAgentModal)- Load robot data from API (
getRobot()) - Load email domains, managers, roles from Team API
- Load agents and MCP servers from API
- Pre-populate form with existing data
- Call
updateRobot()API withrobot_config.clockfor schedule - Handle success/error messages
- Work Schedule panel saves correctly
- Load robot data from API (
- Delete Robot (
AdvancedPanelinConfigTab)- Confirmation dialog with name input
- Call
deleteRobot()API - Handle running execution conflict (409)
- Refresh list after deletion
1-FE.3 UI/UX Enhancements ✅
CreatureLoadingcomponent with organic animations- Breathing aura, floating creature, orbit ring, particles
- Three sizes: small, medium, large
- Used in ConfigTab, ResultsTab, HistoryTab
- Empty state "Create Agent" button with bubble animation
- Cyan, purple, pink glowing bubbles rising
- CSS variable compliance (
--color_mission_button_text) - Consistent loading animations across all tabs
1-FE.4 Verification ✅
- Manual test: Create → List → Get → Update → Delete
- E2E automated test (TODO: Phase 3)
- Permission test: Personal user vs Team user (manual tested)
- Error handling: 400, 403, 404, 409, 500
🟢 Phase 2: Execution Management [Backend ✅ | Frontend ⬜]
Backend: Steps 1-4 ✅ Complete (including UI fields and i18n) Frontend: Step 5 ⬜ Pending Deferred: Trigger/Intervene UI → Phase 5 (requires SSE)
Goal: Execution listing, details, control, and trigger/intervene (single-submit mode)
Risk: 🟢 Low - Wraps existing robot/api functions
Workflow: 1. Implement All Endpoints → 2. Linter Check → 3. Code Review → 4. Unit Tests → 5. Frontend Integration
Step 1: Implement All OpenAPI Endpoints ✅
Location:
yao/openapi/agent/robot/Calls:yao/agent/robot/api/(existing functions)
2.1.1 Types (types.go) ✅
ExecutionFilter- query params for listingExecutionResponse- single execution responseExecutionListResponse- paginated list responseExecutionControlResponse- pause/resume/cancel responseTriggerRequest- trigger execution requestTriggerResponse- trigger result responseInterveneRequest- human intervention requestInterveneResponse- intervention result response
2.1.2 Execution Handlers (execution.go) ✅
Permission Note: Execution permissions are inherited from the parent robot. Check robot's
__yao_team_idand__yao_created_byfor access control.
ListExecutions- GET /v1/agent/robots/:id/executions- Parse query:
status,trigger_type,keyword,page,pagesize - Call
robot/api.ListExecutions() - Permission: Check robot CanRead (via robot ID)
- Parse query:
GetExecution- GET /v1/agent/robots/:id/executions/:exec_id- Call
robot/api.GetExecution() - Permission: Check robot CanRead (via robot ID)
- Call
PauseExecution- POST /v1/agent/robots/:id/executions/:exec_id/pause- Call
robot/api.PauseExecution() - Permission: Check robot CanWrite (via robot ID)
- Call
ResumeExecution- POST /v1/agent/robots/:id/executions/:exec_id/resume- Call
robot/api.ResumeExecution() - Permission: Check robot CanWrite (via robot ID)
- Call
CancelExecution- POST /v1/agent/robots/:id/executions/:exec_id/cancel- Call
robot/api.StopExecution() - Permission: Check robot CanWrite (via robot ID)
- Call
2.1.3 Trigger Handlers (trigger.go) ✅
Permission Note: Same as execution - check robot's permission.
TriggerRobot- POST /v1/agent/robots/:id/trigger- Parse
TriggerRequest(messages, trigger_type) - Call
robot/api.Trigger() - Return execution ID and status
- Permission: Check robot CanWrite (via robot ID)
- Parse
InterveneRobot- POST /v1/agent/robots/:id/intervene- Parse
InterveneRequest(action, messages) - Call
robot/api.Intervene() - Return result
- Permission: Check robot CanWrite (via robot ID)
- Parse
2.1.4 Route Registration (robot.go) ✅
- Add execution routes to
Attach():GET /:id/executionsGET /:id/executions/:exec_idPOST /:id/executions/:exec_id/pausePOST /:id/executions/:exec_id/resumePOST /:id/executions/:exec_id/cancelPOST /:id/triggerPOST /:id/intervene
Step 2: Linter Check ✅
- Run
ReadLintson all modified files - Fix any linter errors
- Verify imports are correct
- Build verification passed
Step 3: Code Review ✅
- Review type definitions (
types.go)ExecutionFilter,ExecutionResponse,ExecutionListResponse,ExecutionControlResponseTriggerRequest,TriggerResponse,InterveneRequest,InterveneResponse- Conversion functions:
NewExecutionListResponse,NewExecutionResponseFromExecution,NewExecutionResponseBrief
- Review permission handling
- All execution/trigger handlers check robot permission first
- Read permission for listing and getting executions
- Write permission for control (pause/resume/cancel), trigger, and intervene
- Permission inherited from parent robot (check via
YaoTeamIDandYaoCreatedBy)
- Review error handling
- Fixed: Use
errors.Is()instead of==for error comparison - Proper HTTP status codes (400, 404, 403, 500)
- Consistent error response format
- Fixed: Use
- Review response formats
- Brief format for list view (omits phase outputs)
- Full format for detail view (includes all fields)
- Consistent with existing robot responses
Step 4: Unit Tests ✅
Location:
yao/openapi/tests/agent/Usestesting.Short()to skip AI/manager-dependent tests
- Create
robot_execution_test.goTestListExecutions- list executions with pagination/filtersTestGetExecution- get execution details, not found casesTestExecutionControl- pause/resume/cancel endpointsTestExecutionPermissions- permission inheritance from robot
- Create
robot_trigger_test.goTestTriggerRobot- trigger with messages, action, invalid bodyTestInterveneRobot- intervene with action, missing action validationTestTriggerPermissions- permission inheritance from robot
- All tests use
testing.Short()to skip AI-dependent tests - Tests compile successfully
- All tests pass (with manager not started gracefully handled)
Step 5: Frontend Integration ⬜
Location:
cui/packages/cui/openapi/agent/robot/Note: Trigger/Intervene API deferred to Phase 5 (waiting for SSE support) Note: Use 1-minute polling for execution list refresh (will switch to SSE in Phase 6)
5.1 Prerequisites ✅
Dependency: Backend improvement plans completed (see "Improvement Plan" sections above)
Backend (Completed):
Executionstruct - addName,CurrentTaskNamefieldsRobotConfigstruct - addDefaultLocalefieldTriggerInputstruct - addLocalefield- Executor - update
Name,CurrentTaskNameat each phase - Store - add
UpdateUIFields()method - Unit tests for UI fields and i18n
Frontend Cleanup (Completed):
- Components already use
exec.id(no changes needed) - Remove
job_idfield fromtypes.ts Remove(mock kept for reference, not used)job_idfrommock/data.ts- Use
name/current_task_namedirectly from API response (string, not{en, cn})
5.2 SDK Types (types.ts) ✅
ExecutionFilterinterfaceExecutionResponseinterface (align with backend)ExecutionListResponseinterfaceExecutionControlResponseinterfaceExecStatus,TriggerType,Phasetype aliases
Deferred to Phase 5 (SSE):
TriggerRequest/TriggerResponseinterfacesInterveneRequest/InterveneResponseinterfaces
5.3 SDK Methods (robots.ts) ✅
ListExecutions(robotId, filter)GetExecution(robotId, execId)PauseExecution(robotId, execId)ResumeExecution(robotId, execId)CancelExecution(robotId, execId)
Deferred to Phase 5 (SSE):
Trigger(robotId, data)Intervene(robotId, data)
5.4 Page Integration ✅
- ActiveTab: Replace mock with
ListExecutions()API- Filter:
status=running|pending - Polling: 1-minute interval (60000ms) - will switch to SSE in Phase 6
- Filter:
- HistoryTab: Replace mock with
ListExecutions()API- Filter:
statusfilter,keywordsearch - Pagination: page/pagesize
- Polling: 1-minute interval for list refresh
- Filter:
- Execution Detail: Call
GetExecution()API- Display execution phases and outputs
- Display
nameandcurrent_task_namefrom API - Display
errorfield for failed executions - Execution controls: Pause/Resume/Cancel buttons (call control APIs)
- Auto-refresh while execution is running (5s for running)
- useRobots hook extended with execution methods
Deferred to Phase 5 (SSE):
Assign Task Modal: CallTrigger()APIGuideExecution: CallIntervene()API
5.5 Polling vs SSE Strategy
Current (Phase 2): Polling
- Refresh execution list every 60 seconds
- Manual refresh button for immediate update
- Acceptable latency for status display
Future (Phase 6): SSE Real-time
GET /robots/:id/executions/stream- real-time execution updatesGET /robots/stream- robot status changes- Instant updates, no polling delay
🟢 Phase 3: Results & Activities ⬜ [Low Risk]
Goal: Deliverables listing and activity feed Risk: 🟢 Low - Read-only queries, derived from existing data
3.1 Backend Prerequisites ⬜
Store Layer (Core implementation)
- Add
ExecutionStore.ListResults()- query deliverables from execution delivery data - Add
ExecutionStore.GetResult()- get single deliverable detail - Add
ExecutionStore.ListActivities()- derive activities from execution history
API Layer (Thin wrappers)
- Create
api/results.gowithListResults(),GetResult()- call store - Create
api/activities.gowithListActivities()- call store
3.2 Results Endpoints ⬜
results.go- results handlers- GET /v1/robots/:id/results
- Parse filters:
trigger_type,keyword,page,pagesize - Call
robot/api.ListResults() - Format response
- Parse filters:
- GET /v1/robots/:id/results/:result_id
- Call
robot/api.GetResult() - Return full delivery content
- Call
- Test:
tests/robot/results_test.go
3.3 Results Types ⬜
- Add to
types.go:ResultResponsestructResultDetailResponsestructDeliveryContentResponsestructDeliveryAttachmentResponsestruct
3.4 Activities Endpoints ⬜
activities.go- activities handlers- GET /v1/robots/activities
- Parse:
limit,since - Call
robot/api.ListActivities() - Format response
- Parse:
- Test:
tests/robot/activities_test.go
3.5 Activity Types ⬜
- Add to
types.go:ActivityResponsestructActivityTypeconstants
3.6 Frontend Integration ⬜
Integrate immediately after backend completion
- SDK: Add results/activities methods to
robot.tslistResults(robotId, params)getResult(robotId, resultId)listActivities(params)
- Page: Results Tab integration
- Page: Activity Feed integration
- Verify: E2E testing
🟢 Phase 4: i18n ⬜ [Low Risk]
Goal: Locale parameter support Risk: 🟢 Low - Additive, optional parameter
4.1 Locale Handling ⬜
- Add
getLocale(r *http.Request)to utils.go - Parse locale from query param, body, or header
- Add
Localefield to context if needed
4.2 Localized Responses ⬜
- Localize
display_namein RobotResponse - Localize
descriptionin RobotResponse - Localize
namein ExecutionResponse (derive from goals/input) - Localize
current_task_namein ExecutionResponse
4.3 Frontend Integration ⬜
Integrate immediately after backend completion
- SDK: Add
localeparameter support to all API calls - Page: Use current language setting when calling APIs
- Verify: Data correctly localized after language switch
🟡 Phase 5: Multi-turn Chat API + Trigger/Intervene UI ⬜ [Medium Risk - Deferred]
Frontend Fallback: Single-submit mode (user input → immediate execution) Risk: 🟡 Medium - New stateful component Dependency: Requires SSE infrastructure (partially)
Goal: Multi-turn conversation before execution + Human trigger/intervene UI
5.1 Backend Prerequisites ⬜
- Create
store/conversation.go- temporary conversation storage (redis/memory) - Create
types/conversation.go- Conversation, ChatRequest, ChatResponse types - Create
api/chat.go- Chat() handler with LLM call - Extend
api/trigger.go- supportconversation_idparameter
5.2 Chat Endpoint ⬜
- POST /v1/robots/:id/chat (SSE)
- Parse ChatRequest (conversation_id, messages, attachments)
- Create or continue conversation
- Call LLM for response
- Store updated conversation
- Return assistant message + conversation_id
- Test:
tests/robot/chat_test.go
5.3 Trigger with Conversation ⬜
- Extend POST /v1/robots/:id/trigger
- Accept
conversation_idparameter - Use conversation history as execution input
- Auto-cleanup conversation after execution starts
5.4 Frontend Trigger/Intervene Integration (Deferred from Phase 2) ⬜
Note: These features require SSE for proper UX (streaming response) Currently backend
/triggerand/interveneendpoints exist but return immediately Frontend needs streaming response to show assistant's reaction before confirming
SDK Types:
TriggerRequest/TriggerResponseinterfacesInterveneRequest/InterveneResponseinterfacesChatMessageinterface for multi-turn
SDK Methods:
Trigger(robotId, data)- with SSE supportIntervene(robotId, data)- with SSE supportChat(robotId, data)- multi-turn conversation SSE
Page Integration:
- AssignTaskDrawer: Multi-turn chat before trigger
- GuideExecutionDrawer: Multi-turn intervention
- Real-time streaming response display
🟡 Phase 6: Real-time SSE Streams ⬜ [Medium Risk - Deferred]
Frontend Current: Polling every 60 seconds (1 minute) Frontend Future: SSE streams for instant updates Risk: 🟡 Medium - Requires modification of executor/manager
Goal: SSE streams for real-time status updates, replacing polling
6.1 Backend Event System ⬜
Need to add in robot/:
- Create
events/bus.go- Event bus for pub/sub - Integrate event publishing in
manager/manager.go - Integrate event publishing in
executor/standard/executor.go - Publish: robot_status, execution_start, execution_complete, phase, task events
6.2 Robot Status Stream ⬜
stream.go- stream handlers- GET /v1/robots/stream
- Subscribe to manager status updates
- Stream
robot_statusevents - Stream
execution_startevents - Stream
execution_completeevents - Stream
activityevents
- Test:
tests/robot/stream_test.go
6.3 Execution Progress Stream ⬜
- GET /v1/robots/:id/executions/:exec_id/stream
- Subscribe to execution updates
- Stream
phaseevents - Stream
task_start/task_completeevents - Stream
messageevents - Stream
deliveryevent - Stream
complete/errorevents
- Test:
tests/robot/execution_stream_test.go
Backend Extensions Required
Architecture: Store layer handles CRUD, API layer handles business logic. This enables reuse across Golang API, JSAPI, and Yao Process.
robot/store/ Extensions (Core CRUD)
| Function | Phase | Risk | Status | Description |
|---|---|---|---|---|
RobotStore.Save() |
1 | 🟢 Low | ✅ | Create/update robot member |
RobotStore.Get() |
1 | 🟢 Low | ✅ | Get robot by member_id |
RobotStore.List() |
1 | 🟢 Low | ✅ | List robots with filters |
RobotStore.Delete() |
1 | 🟢 Low | ✅ | Delete robot member |
RobotStore.UpdateConfig() |
1 | 🟢 Low | ✅ | Update config only |
RobotStore.UpdateStatus() |
1 | 🟢 Low | ✅ | Update status only |
ExecutionStore.ListResults() |
3 | 🟢 Low | ⬜ | Query deliverables from executions |
ExecutionStore.GetResult() |
3 | 🟢 Low | ⬜ | Get single deliverable |
ExecutionStore.ListActivities() |
3 | 🟢 Low | ⬜ | Derive activities from history |
| Conversation store | 5 | 🟡 Medium | ⬜ | Temporary chat history (Deferred) |
robot/types/ Extensions
| Type/Field | Phase | Risk | Status | Description |
|---|---|---|---|---|
Robot.Bio |
1 | 🟢 Low | ✅ | Add field, maps to __yao.member.bio |
| Execution name derivation | 2 | 🟢 Low | ⬜ | Derive in OpenAPI layer from goals or input |
Note:
Robot.Nameis NOT needed. Frontendnamemaps to existingRobot.MemberID.
robot/cache/ Extensions
| File | Phase | Risk | Status | Description |
|---|---|---|---|---|
load.go |
1 | 🟢 Low | ✅ | Add bio to memberFields slice |
robot/utils/ Extensions
| File | Phase | Risk | Status | Description |
|---|---|---|---|---|
convert.go |
1 | 🟢 Low | ✅ | Unified type conversion utilities |
convert_test.go |
1 | 🟢 Low | ✅ | Tests for conversion utilities |
robot/api/ Extensions (Thin wrappers calling store)
| Function | Phase | Risk | Status | Description |
|---|---|---|---|---|
CreateRobot() |
1 | 🟢 Low | ✅ | Call store.RobotStore.Save() + cache refresh |
UpdateRobot() |
1 | 🟢 Low | ✅ | Partial update + cache refresh |
RemoveRobot() |
1 | 🟢 Low | ✅ | Call store.RobotStore.Delete() + cache invalidate |
GetRobotResponse() |
1 | 🟢 Low | ✅ | Get robot as API response |
ListResults() |
3 | 🟢 Low | ⬜ | Call store.ExecutionStore.ListResults() |
GetResult() |
3 | 🟢 Low | ⬜ | Call store.ExecutionStore.GetResult() |
ListActivities() |
3 | 🟢 Low | ⬜ | Call store.ExecutionStore.ListActivities() |
RetryExecution() |
2 | 🟢 Low | ⬜ | Re-trigger with same input |
Chat() |
5 | 🟡 Medium | ⬜ | Multi-turn conversation (Deferred) |
Event System (Phase 6 - Deferred)
| Component | Phase | Risk | Description |
|---|---|---|---|
| Event bus | 6 | 🟡 Medium | Pub/sub for real-time updates |
| Manager events | 6 | 🟡 Medium | Publish robot status changes |
| Executor events | 6 | 🟡 Medium | Publish execution progress |
Testing Strategy
Test Files Structure
yao/openapi/tests/robot/
├── list_test.go
├── get_test.go
├── create_test.go
├── update_test.go
├── delete_test.go
├── execution_list_test.go
├── execution_get_test.go
├── execution_control_test.go
├── trigger_test.go
├── intervene_test.go
├── results_test.go
├── activities_test.go
├── stream_test.go
└── execution_stream_test.go
Test Utilities
- Create test robot helper
- Create test execution helper
- SSE client for streaming tests
- Mock data generators
Progress Tracking
| Phase | Risk | Backend | Frontend | Description |
|---|---|---|---|---|
| 1. Core CRUD | 🟢 | ✅ | ✅ | Robot CRUD endpoints |
| 1-FE Frontend Integration | 🟢 | - | ✅ | SDK ✅, Page Integration ✅, UI/UX ✅ |
| 1.5 Manager Lifecycle | 🟢 | ✅ | - | Auto-start, auto-reload, graceful shutdown |
| 2. Execution | 🟢 | ✅ | ⬜ | Execution listing, control, trigger (backend complete with UI fields & i18n) |
| 3. Results/Activities | 🟢 | ⬜ | ⬜ | Deliverables and activity feed |
| 4. i18n | 🟢 | ✅ | ⬜ | Locale parameter support (backend executor i18n complete) |
| 5. Chat API | 🟡 | ⬜ | ⬜ | Multi-turn conversation (Deferred) |
| 6. SSE Streams | 🟡 | ⬜ | ⬜ | Real-time status updates (Deferred) |
Legend: ⬜ Not started | 🟡 In progress | ✅ Complete
Phase 1 Detailed Status
| Component | Status | Notes |
|---|---|---|
types.Robot.Bio |
✅ | Field added |
cache/load.go |
✅ | bio in memberFields |
store/robot.go |
✅ | Full CRUD with permission fields |
store/robot_test.go |
✅ | Integration tests |
api/robot.go |
✅ | Create/Update/Remove/GetResponse |
api/types.go |
✅ | Request/Response types, AuthScope |
api/robot_test.go |
✅ | API tests |
utils/convert.go |
✅ | Type conversion utilities |
utils/convert_test.go |
✅ | Unit tests |
openapi/agent/robot/robot.go |
✅ | Route registration with Attach() |
openapi/agent/robot/types.go |
✅ | HTTP request/response types |
openapi/agent/robot/list.go |
✅ | List robots handler with permission filter |
openapi/agent/robot/detail.go |
✅ | CRUD handlers with permission checks |
openapi/agent/robot/permission.go |
✅ | Permission check functions (CanRead/CanWrite) |
openapi/agent/robot/utils.go |
✅ | Helper functions |
openapi/agent/agent.go |
✅ | Robot routes registered |
openapi/tests/agent/robot_test.go |
✅ | Integration tests + Permission tests |
Quick Reference
Current Location
yao/openapi/agent/robot/ # This directory (sub-package under agent)
├── DESIGN.md # Design document ✅
├── TODO.md # This file ✅
├── robot.go # Route registration (Attach function) ✅
├── types.go # All request/response types ✅
├── list.go # GET /v1/agent/robots ✅
├── detail.go # GET/POST/PUT/DELETE /v1/agent/robots/:id ✅
├── permission.go # Permission check functions (CanRead/CanWrite) ✅
├── utils.go # Utilities ✅
├── execution.go # Execution endpoints (Phase 2)
├── trigger.go # Trigger/Intervene SSE (Phase 2)
├── results.go # Results endpoints (Phase 3)
├── activities.go # Activities endpoint (Phase 3)
├── stream.go # Real-time streams (Phase 6 - Deferred)
└── filter.go # Query filtering (optional)
Parent Directory
yao/openapi/agent/
├── agent.go # MODIFY: add robot.Attach() call
├── assistant.go # Existing
├── filter.go # Existing
├── models.go # Existing
├── types.go # Existing
│
└── robot/ # NEW sub-package (this directory)
└── ...
Route Registration (in agent/agent.go)
import "github.com/yaoapp/yao/openapi/agent/robot"
func Attach(group *gin.RouterGroup, oauth types.OAuth) {
group.Use(oauth.Guard)
// Existing assistant routes
group.GET("/assistants", ListAssistants)
group.POST("/assistants", CreateAssistant)
group.GET("/assistants/tags", ListAssistantTags)
group.GET("/assistants/:id", GetAssistant)
group.GET("/assistants/:id/info", GetAssistantInfo)
group.PUT("/assistants/:id", UpdateAssistant)
// Robot routes (NEW)
robot.Attach(group.Group("/robots"), oauth)
}
Dependencies
| Package | Usage |
|---|---|
yao/agent/robot/api |
Go API functions (Get, List, Trigger, etc.) |
yao/agent/robot/types |
Robot types (Robot, Execution, etc.) |
yao/openapi/oauth |
Authentication, Guard middleware |
yao/openapi/oauth/types |
OAuth types (AuthorizedInfo) |
yao/openapi/response |
Response helpers |
Import Path
package robot
import (
"github.com/gin-gonic/gin"
robotapi "github.com/yaoapp/yao/agent/robot/api"
robottypes "github.com/yaoapp/yao/agent/robot/types"
"github.com/yaoapp/yao/openapi/oauth/types"
)
Notes
Priority
| Priority | Phase | Required For | Risk |
|---|---|---|---|
| 1 | Phase 1 (CRUD) | Basic UI functionality | 🟢 Low |
| 2 | Phase 2 (Execution) | Active/History tabs, Assign Task | 🟢 Low |
| 3 | Phase 3 (Results) | Results tab | 🟢 Low |
| 4 | Phase 4 (i18n) | Multi-language support | 🟢 Low |
| 5 | Phase 5 (Chat) | Enhanced UX (deferred) | 🟡 Medium |
| 6 | Phase 6 (SSE) | Real-time updates (deferred) | 🟡 Medium |
Frontend Fallbacks
| Feature | Full Implementation | Fallback |
|---|---|---|
| Assign Task | Multi-turn chat → Confirm → Execute | Single-submit → Execute |
| Real-time Status | SSE push | Polling every 3-5s |
Frontend Integration
Execute immediately after each phase backend completion:
- SDK Implementation -
cui/packages/cui/openapi/agent/robot/ - Type Definitions - TypeScript request/response types
- Hook Implementation -
cui/packages/cui/hooks/useRobots.ts - Page Integration - Replace mock data, call real APIs
- E2E Verification - Full flow testing
File Locations:
cui/packages/cui/
├── openapi/
│ └── agent/
│ └── robot/
│ ├── types.ts # TypeScript types
│ ├── robots.ts # AgentRobots SDK class
│ └── index.ts # Exports
├── hooks/
│ └── useRobots.ts # React hook for robot API calls
├── styles/
│ └── preset/
│ └── vars.less # CSS variables (--color_mission_button_text)
└── pages/
└── mission-control/
├── index.tsx # Robot list (grid) page
├── index.less # Styles with bubble animations
└── components/
├── AgentModal/ # Robot detail modal
├── AddAgentModal/ # Create robot modal
└── CreatureLoading/ # Branded loading component
├── index.tsx
└── index.less
Incremental Deployment
Each phase independently deliverable:
| Phase | Backend | Frontend | Verifiable Features |
|---|---|---|---|
| 1 | ✅ | ✅ | Robot CRUD basic management |
| 2 | ✅ | ⬜ | Execution list/control/trigger (backend with UI fields & i18n) |
| 3 | ⬜ | ⬜ | Results/Activities viewing |
| 4 | ✅ | ⬜ | Multi-language support (backend executor i18n) |
| 5 | ⬜ | ⬜ | Multi-turn chat UX (optional) |
| 6 | ⬜ | ⬜ | Real-time push (optional) |