mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-29 14:02:19 +00:00
* feat(agent): pure orchestrator pattern with per-skill delegation tools (#478) Refactors the main agent from a direct tool-calling model to a pure orchestrator that delegates all work through dynamically generated tools. Architecture changes: - Orchestrator only sees generated tools (notion, gmail, research, run_code, review_code, plan, spawn_subagent) — skill tools are architecturally unreachable from the main agent - Each installed skill auto-generates a delegation tool at build time (SkillDelegationTool) that routes to skills_agent with the correct skill_filter - Static archetype tools (research, run_code, etc.) delegate to their respective sub-agents - visible_tool_specs filters the function-calling schema sent to the provider, enforcing the orchestrator boundary at the API level Prompt changes: - Rewrote AGENTS.md as a lean orchestrator prompt — no more routing tables or agent_id instructions - Orchestrator skips TOOLS.md, MEMORY.md, HEARTBEAT.md (~6k tokens saved per turn) — subagents get tool specs from the registry - Workspace .md files auto-sync via builtin-hash mechanism so prompt updates ship automatically to existing installs Bug fixes: - ModelSpec::Hint now resolves to {hint}-v1 (e.g. agentic-v1) instead of hint:agentic which the backend rejected - validate_skill_filter now uses skill_id from the engine tuple instead of splitting on __ in the raw tool name (which always failed) - Memory context forwarded to subagents via ParentExecutionContext Observability: - Added [agent] tagged logs for tool responses, agent state transitions, and delegation decisions throughout turn.rs See docs/agent-prompt-architecture.excalidraw for the visual diagram. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * style: rustfmt orchestrator_tools.rs Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * style: cargo fmt Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address CodeRabbit review — dispatch guard, fork specs, decouple sync - Enforce visible-tool allowlist at dispatch time (not just schema) - Fork mode uses visible_tool_specs (not full registry) - De-duplicate spawn_subagent when extending orchestrator tools - Raw tool output moved to debug level, info level logs metadata only - Decouple workspace file sync from prompt rendering so skipped files still get synced to disk Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
505 lines
15 KiB
Plaintext
505 lines
15 KiB
Plaintext
{
|
|
"type": "excalidraw",
|
|
"version": 2,
|
|
"source": "openhuman-478",
|
|
"elements": [
|
|
{
|
|
"id": "title",
|
|
"type": "text",
|
|
"x": 300,
|
|
"y": 20,
|
|
"width": 500,
|
|
"height": 40,
|
|
"text": "OpenHuman Agent Prompt Architecture",
|
|
"fontSize": 28,
|
|
"fontFamily": 1,
|
|
"textAlign": "center",
|
|
"strokeColor": "#1e1e1e",
|
|
"backgroundColor": "transparent",
|
|
"fillStyle": "solid",
|
|
"strokeWidth": 1,
|
|
"roundness": null,
|
|
"roughness": 0,
|
|
"opacity": 100,
|
|
"angle": 0,
|
|
"seed": 1,
|
|
"version": 1,
|
|
"isDeleted": false,
|
|
"boundElements": null,
|
|
"updated": 1,
|
|
"link": null,
|
|
"locked": false,
|
|
"groupIds": []
|
|
},
|
|
{
|
|
"id": "orchestrator-box",
|
|
"type": "rectangle",
|
|
"x": 50,
|
|
"y": 80,
|
|
"width": 400,
|
|
"height": 380,
|
|
"strokeColor": "#1971c2",
|
|
"backgroundColor": "#d0ebff",
|
|
"fillStyle": "solid",
|
|
"strokeWidth": 2,
|
|
"roundness": { "type": 3 },
|
|
"roughness": 0,
|
|
"opacity": 100,
|
|
"angle": 0,
|
|
"seed": 2,
|
|
"version": 1,
|
|
"isDeleted": false,
|
|
"boundElements": null,
|
|
"updated": 1,
|
|
"link": null,
|
|
"locked": false,
|
|
"groupIds": []
|
|
},
|
|
{
|
|
"id": "orchestrator-title",
|
|
"type": "text",
|
|
"x": 70,
|
|
"y": 90,
|
|
"width": 360,
|
|
"height": 30,
|
|
"text": "ORCHESTRATOR (main agent)",
|
|
"fontSize": 20,
|
|
"fontFamily": 1,
|
|
"textAlign": "left",
|
|
"strokeColor": "#1971c2",
|
|
"backgroundColor": "transparent",
|
|
"fillStyle": "solid",
|
|
"strokeWidth": 1,
|
|
"roundness": null,
|
|
"roughness": 0,
|
|
"opacity": 100,
|
|
"angle": 0,
|
|
"seed": 3,
|
|
"version": 1,
|
|
"isDeleted": false,
|
|
"boundElements": null,
|
|
"updated": 1,
|
|
"link": null,
|
|
"locked": false,
|
|
"groupIds": []
|
|
},
|
|
{
|
|
"id": "orchestrator-model",
|
|
"type": "text",
|
|
"x": 70,
|
|
"y": 115,
|
|
"width": 360,
|
|
"height": 20,
|
|
"text": "Model: reasoning-v1",
|
|
"fontSize": 14,
|
|
"fontFamily": 3,
|
|
"textAlign": "left",
|
|
"strokeColor": "#868e96",
|
|
"backgroundColor": "transparent",
|
|
"fillStyle": "solid",
|
|
"strokeWidth": 1,
|
|
"roundness": null,
|
|
"roughness": 0,
|
|
"opacity": 100,
|
|
"angle": 0,
|
|
"seed": 4,
|
|
"version": 1,
|
|
"isDeleted": false,
|
|
"boundElements": null,
|
|
"updated": 1,
|
|
"link": null,
|
|
"locked": false,
|
|
"groupIds": []
|
|
},
|
|
{
|
|
"id": "orchestrator-prompt-files",
|
|
"type": "text",
|
|
"x": 70,
|
|
"y": 145,
|
|
"width": 360,
|
|
"height": 200,
|
|
"text": "System prompt (from workspace .md files):\n\n✅ AGENTS.md — Orchestrator routing logic\n \"Pick the right tool, synthesise the result\"\n\n✅ SOUL.md — Personality, voice, tone\n \"Smart friend who helps get stuff done\"\n\n✅ IDENTITY.md — Mission, values, boundaries\n \"What OpenHuman is and isn't\"\n\n✅ USER.md — User adaptation rules\n \"Traders want speed, researchers want depth\"\n\n✅ BOOTSTRAP.md — First interaction flow\n \"Greet warmly, discover role, ask what's needed\"",
|
|
"fontSize": 12,
|
|
"fontFamily": 3,
|
|
"textAlign": "left",
|
|
"strokeColor": "#1e1e1e",
|
|
"backgroundColor": "transparent",
|
|
"fillStyle": "solid",
|
|
"strokeWidth": 1,
|
|
"roundness": null,
|
|
"roughness": 0,
|
|
"opacity": 100,
|
|
"angle": 0,
|
|
"seed": 5,
|
|
"version": 1,
|
|
"isDeleted": false,
|
|
"boundElements": null,
|
|
"updated": 1,
|
|
"link": null,
|
|
"locked": false,
|
|
"groupIds": []
|
|
},
|
|
{
|
|
"id": "orchestrator-skipped",
|
|
"type": "text",
|
|
"x": 70,
|
|
"y": 370,
|
|
"width": 360,
|
|
"height": 80,
|
|
"text": "Skipped (not needed for routing):\n\n❌ TOOLS.md — Skill tool docs (subagents have specs)\n❌ MEMORY.md — Memory protocol (auto-injected)\n❌ HEARTBEAT.md — Cron config (handled by system)",
|
|
"fontSize": 12,
|
|
"fontFamily": 3,
|
|
"textAlign": "left",
|
|
"strokeColor": "#e03131",
|
|
"backgroundColor": "transparent",
|
|
"fillStyle": "solid",
|
|
"strokeWidth": 1,
|
|
"roundness": null,
|
|
"roughness": 0,
|
|
"opacity": 100,
|
|
"angle": 0,
|
|
"seed": 6,
|
|
"version": 1,
|
|
"isDeleted": false,
|
|
"boundElements": null,
|
|
"updated": 1,
|
|
"link": null,
|
|
"locked": false,
|
|
"groupIds": []
|
|
},
|
|
{
|
|
"id": "tools-box",
|
|
"type": "rectangle",
|
|
"x": 500,
|
|
"y": 80,
|
|
"width": 350,
|
|
"height": 250,
|
|
"strokeColor": "#2f9e44",
|
|
"backgroundColor": "#d8f5a2",
|
|
"fillStyle": "solid",
|
|
"strokeWidth": 2,
|
|
"roundness": { "type": 3 },
|
|
"roughness": 0,
|
|
"opacity": 100,
|
|
"angle": 0,
|
|
"seed": 7,
|
|
"version": 1,
|
|
"isDeleted": false,
|
|
"boundElements": null,
|
|
"updated": 1,
|
|
"link": null,
|
|
"locked": false,
|
|
"groupIds": []
|
|
},
|
|
{
|
|
"id": "tools-title",
|
|
"type": "text",
|
|
"x": 520,
|
|
"y": 90,
|
|
"width": 310,
|
|
"height": 30,
|
|
"text": "ORCHESTRATOR TOOLS",
|
|
"fontSize": 20,
|
|
"fontFamily": 1,
|
|
"textAlign": "left",
|
|
"strokeColor": "#2f9e44",
|
|
"backgroundColor": "transparent",
|
|
"fillStyle": "solid",
|
|
"strokeWidth": 1,
|
|
"roundness": null,
|
|
"roughness": 0,
|
|
"opacity": 100,
|
|
"angle": 0,
|
|
"seed": 8,
|
|
"version": 1,
|
|
"isDeleted": false,
|
|
"boundElements": null,
|
|
"updated": 1,
|
|
"link": null,
|
|
"locked": false,
|
|
"groupIds": []
|
|
},
|
|
{
|
|
"id": "tools-content",
|
|
"type": "text",
|
|
"x": 520,
|
|
"y": 120,
|
|
"width": 310,
|
|
"height": 200,
|
|
"text": "Visible to LLM (function-calling schema):\n\n🔧 notion → skills_agent(filter:notion)\n🔧 gmail → skills_agent(filter:gmail)\n🔧 slack → skills_agent(filter:slack)\n (dynamic: 1 per installed skill)\n\n🔧 research → researcher subagent\n🔧 run_code → code_executor subagent\n🔧 review_code → critic subagent\n🔧 plan → planner subagent\n (static: always available)\n\n🔧 spawn_subagent → fallback (fork, custom)",
|
|
"fontSize": 12,
|
|
"fontFamily": 3,
|
|
"textAlign": "left",
|
|
"strokeColor": "#1e1e1e",
|
|
"backgroundColor": "transparent",
|
|
"fillStyle": "solid",
|
|
"strokeWidth": 1,
|
|
"roundness": null,
|
|
"roughness": 0,
|
|
"opacity": 100,
|
|
"angle": 0,
|
|
"seed": 9,
|
|
"version": 1,
|
|
"isDeleted": false,
|
|
"boundElements": null,
|
|
"updated": 1,
|
|
"link": null,
|
|
"locked": false,
|
|
"groupIds": []
|
|
},
|
|
{
|
|
"id": "subagent-box",
|
|
"type": "rectangle",
|
|
"x": 50,
|
|
"y": 500,
|
|
"width": 800,
|
|
"height": 300,
|
|
"strokeColor": "#e8590c",
|
|
"backgroundColor": "#fff4e6",
|
|
"fillStyle": "solid",
|
|
"strokeWidth": 2,
|
|
"roundness": { "type": 3 },
|
|
"roughness": 0,
|
|
"opacity": 100,
|
|
"angle": 0,
|
|
"seed": 10,
|
|
"version": 1,
|
|
"isDeleted": false,
|
|
"boundElements": null,
|
|
"updated": 1,
|
|
"link": null,
|
|
"locked": false,
|
|
"groupIds": []
|
|
},
|
|
{
|
|
"id": "subagent-title",
|
|
"type": "text",
|
|
"x": 70,
|
|
"y": 510,
|
|
"width": 760,
|
|
"height": 30,
|
|
"text": "SUB-AGENTS (spawned by orchestrator tools)",
|
|
"fontSize": 20,
|
|
"fontFamily": 1,
|
|
"textAlign": "left",
|
|
"strokeColor": "#e8590c",
|
|
"backgroundColor": "transparent",
|
|
"fillStyle": "solid",
|
|
"strokeWidth": 1,
|
|
"roundness": null,
|
|
"roughness": 0,
|
|
"opacity": 100,
|
|
"angle": 0,
|
|
"seed": 11,
|
|
"version": 1,
|
|
"isDeleted": false,
|
|
"boundElements": null,
|
|
"updated": 1,
|
|
"link": null,
|
|
"locked": false,
|
|
"groupIds": []
|
|
},
|
|
{
|
|
"id": "subagent-content",
|
|
"type": "text",
|
|
"x": 70,
|
|
"y": 545,
|
|
"width": 760,
|
|
"height": 245,
|
|
"text": "Each subagent gets a narrow system prompt: archetype .md + filtered tool specs + workspace dir\nAll subagents: omit_identity=true, omit_memory_context=true, omit_skills_catalog=true\nMemory context auto-forwarded from parent via ParentExecutionContext.memory_context\n\n┌──────────────────┬────────────────────────────────────┬──────────────┬───────────────┐\n│ Agent │ Prompt file (compiled-in) │ Model │ Safety preamble│\n├──────────────────┼────────────────────────────────────┼──────────────┼───────────────┤\n│ skills_agent │ archetypes/skills_agent.md │ agentic-v1 │ ✅ yes │\n│ researcher │ archetypes/researcher.md │ agentic-v1 │ ❌ no │\n│ code_executor │ archetypes/code_executor.md │ coding-v1 │ ✅ yes │\n│ critic │ archetypes/critic.md │ agentic-v1 │ ❌ no │\n│ planner │ PLANNER.md │ reasoning-v1 │ ❌ no │\n│ tool_maker │ archetypes/code_executor.md (shared)│ coding-v1 │ ✅ yes │\n│ archivist │ archetypes/archivist.md │ local-v1 │ ❌ no │\n│ fork │ (replays parent's exact prompt) │ inherited │ inherited │\n└──────────────────┴────────────────────────────────────┴──────────────┴───────────────┘\n\nSubagents DO NOT use workspace .md files (SOUL, IDENTITY, USER, BOOTSTRAP, TOOLS, MEMORY).\nThey only see: their archetype prompt + filtered ToolSpec schemas + [Context] block from parent.",
|
|
"fontSize": 12,
|
|
"fontFamily": 3,
|
|
"textAlign": "left",
|
|
"strokeColor": "#1e1e1e",
|
|
"backgroundColor": "transparent",
|
|
"fillStyle": "solid",
|
|
"strokeWidth": 1,
|
|
"roundness": null,
|
|
"roughness": 0,
|
|
"opacity": 100,
|
|
"angle": 0,
|
|
"seed": 12,
|
|
"version": 1,
|
|
"isDeleted": false,
|
|
"boundElements": null,
|
|
"updated": 1,
|
|
"link": null,
|
|
"locked": false,
|
|
"groupIds": []
|
|
},
|
|
{
|
|
"id": "arrow-orch-to-tools",
|
|
"type": "arrow",
|
|
"x": 450,
|
|
"y": 200,
|
|
"width": 50,
|
|
"height": 0,
|
|
"points": [[0, 0], [50, 0]],
|
|
"strokeColor": "#1e1e1e",
|
|
"strokeWidth": 2,
|
|
"fillStyle": "solid",
|
|
"roughness": 0,
|
|
"opacity": 100,
|
|
"angle": 0,
|
|
"seed": 13,
|
|
"version": 1,
|
|
"isDeleted": false,
|
|
"boundElements": null,
|
|
"updated": 1,
|
|
"link": null,
|
|
"locked": false,
|
|
"groupIds": [],
|
|
"startBinding": null,
|
|
"endBinding": null,
|
|
"startArrowhead": null,
|
|
"endArrowhead": "arrow",
|
|
"roundness": null
|
|
},
|
|
{
|
|
"id": "arrow-tools-to-subagents",
|
|
"type": "arrow",
|
|
"x": 550,
|
|
"y": 330,
|
|
"width": 0,
|
|
"height": 170,
|
|
"points": [[0, 0], [0, 170]],
|
|
"strokeColor": "#e8590c",
|
|
"strokeWidth": 2,
|
|
"fillStyle": "solid",
|
|
"roughness": 0,
|
|
"opacity": 100,
|
|
"angle": 0,
|
|
"seed": 14,
|
|
"version": 1,
|
|
"isDeleted": false,
|
|
"boundElements": null,
|
|
"updated": 1,
|
|
"link": null,
|
|
"locked": false,
|
|
"groupIds": [],
|
|
"startBinding": null,
|
|
"endBinding": null,
|
|
"startArrowhead": null,
|
|
"endArrowhead": "arrow",
|
|
"roundness": null
|
|
},
|
|
{
|
|
"id": "arrow-label-1",
|
|
"type": "text",
|
|
"x": 460,
|
|
"y": 180,
|
|
"width": 40,
|
|
"height": 16,
|
|
"text": "calls",
|
|
"fontSize": 12,
|
|
"fontFamily": 3,
|
|
"textAlign": "center",
|
|
"strokeColor": "#868e96",
|
|
"backgroundColor": "transparent",
|
|
"fillStyle": "solid",
|
|
"strokeWidth": 1,
|
|
"roundness": null,
|
|
"roughness": 0,
|
|
"opacity": 100,
|
|
"angle": 0,
|
|
"seed": 15,
|
|
"version": 1,
|
|
"isDeleted": false,
|
|
"boundElements": null,
|
|
"updated": 1,
|
|
"link": null,
|
|
"locked": false,
|
|
"groupIds": []
|
|
},
|
|
{
|
|
"id": "arrow-label-2",
|
|
"type": "text",
|
|
"x": 555,
|
|
"y": 400,
|
|
"width": 120,
|
|
"height": 16,
|
|
"text": "run_subagent()",
|
|
"fontSize": 12,
|
|
"fontFamily": 3,
|
|
"textAlign": "left",
|
|
"strokeColor": "#868e96",
|
|
"backgroundColor": "transparent",
|
|
"fillStyle": "solid",
|
|
"strokeWidth": 1,
|
|
"roundness": null,
|
|
"roughness": 0,
|
|
"opacity": 100,
|
|
"angle": 0,
|
|
"seed": 16,
|
|
"version": 1,
|
|
"isDeleted": false,
|
|
"boundElements": null,
|
|
"updated": 1,
|
|
"link": null,
|
|
"locked": false,
|
|
"groupIds": []
|
|
},
|
|
{
|
|
"id": "memory-flow",
|
|
"type": "text",
|
|
"x": 500,
|
|
"y": 360,
|
|
"width": 350,
|
|
"height": 70,
|
|
"text": "Data flowing to subagents:\n→ ParentExecutionContext.memory_context\n→ ParentExecutionContext.all_tools (full registry)\n→ ParentExecutionContext.provider (shared)",
|
|
"fontSize": 11,
|
|
"fontFamily": 3,
|
|
"textAlign": "left",
|
|
"strokeColor": "#5c940d",
|
|
"backgroundColor": "transparent",
|
|
"fillStyle": "solid",
|
|
"strokeWidth": 1,
|
|
"roundness": null,
|
|
"roughness": 0,
|
|
"opacity": 100,
|
|
"angle": 0,
|
|
"seed": 17,
|
|
"version": 1,
|
|
"isDeleted": false,
|
|
"boundElements": null,
|
|
"updated": 1,
|
|
"link": null,
|
|
"locked": false,
|
|
"groupIds": []
|
|
},
|
|
{
|
|
"id": "file-sync-note",
|
|
"type": "text",
|
|
"x": 50,
|
|
"y": 830,
|
|
"width": 800,
|
|
"height": 80,
|
|
"text": "FILE SYNC: Workspace .md files are auto-synced from compiled-in defaults.\nA hash of each built-in is stored in .{filename}.builtin-hash — when the code ships\na new version, the hash changes and the disk file is overwritten automatically.\nUser edits between releases are preserved; code updates always win.",
|
|
"fontSize": 12,
|
|
"fontFamily": 3,
|
|
"textAlign": "left",
|
|
"strokeColor": "#868e96",
|
|
"backgroundColor": "#f8f9fa",
|
|
"fillStyle": "solid",
|
|
"strokeWidth": 1,
|
|
"roundness": null,
|
|
"roughness": 0,
|
|
"opacity": 100,
|
|
"angle": 0,
|
|
"seed": 18,
|
|
"version": 1,
|
|
"isDeleted": false,
|
|
"boundElements": null,
|
|
"updated": 1,
|
|
"link": null,
|
|
"locked": false,
|
|
"groupIds": []
|
|
}
|
|
],
|
|
"appState": {
|
|
"gridSize": null,
|
|
"viewBackgroundColor": "#ffffff"
|
|
},
|
|
"files": {}
|
|
}
|