Skip to main content

Skills Architecture

CLEO v0.70.0+ uses a 2-tier universal subagent architecture where all work is delegated to a single agent type (cleo-subagent) with context-specific protocol injection.

2-Tier Architecture

┌─────────────────────────────────────────────────────────────┐
│                    TIER 0: ORCHESTRATOR                     │
│                    (ct-orchestrator)                        │
├─────────────────────────────────────────────────────────────┤
│  • Human-in-the-Loop entry point                            │
│  • Coordinates workflows                                    │
│  • Pre-resolves ALL tokens                                  │
│  • Reads manifest summaries only                            │
│  • NEVER reads full research files                          │
│  • Context budget: 10K tokens                               │
└─────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────┐
│                 TIER 1: CLEO-SUBAGENT                       │
│               (universal executor)                          │
├─────────────────────────────────────────────────────────────┤
│  • Receives fully-resolved prompts                          │
│  • Loads skill via protocol injection                       │
│  • Executes work within skill constraints                   │
│  • Outputs: file + manifest entry + summary                 │
│  • Returns ONLY summary message                             │
└─────────────────────────────────────────────────────────────┘
Anti-Pattern: Do NOT spawn skill-specific agents like ct-research-agent. Always spawn cleo-subagent with the research protocol injected.

Protocol Injection Flow

When spawning a subagent, the orchestrator:
  1. Selects skill via dispatch matrix
  2. Reads skill SKILL.md and relevant protocols
  3. Resolves ALL tokens (TASK_ID, DATE, EPIC_ID, etc.)
  4. Composes prompt with base protocol + conditional protocol
  5. Spawns cleo-subagent with the composed prompt
┌─────────────────────────────────────────────────────────────┐
│                  PROTOCOL COMPOSITION                       │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. Base Protocol (agents/cleo-subagent/AGENT.md)          │
│     • Lifecycle rules                                       │
│     • Output format requirements                            │
│     • Manifest entry format                                 │
│     • Return message constraints                            │
│                                                             │
│  2. Conditional Protocol (skills/ct-*/SKILL.md)            │
│     • Skill-specific instructions                           │
│     • Domain knowledge                                      │
│     • Tool recommendations                                  │
│     • Output templates                                      │
│                                                             │
│  3. Token Resolution                                        │
│     • {{TASK_ID}} → T1234                                  │
│     • {{EPIC_ID}} → T1200                                  │
│     • {{DATE}} → 2026-01-27                                │
│     • {{OUTPUT_DIR}} → claudedocs/agent-outputs            │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Dispatch Algorithm

skill_auto_dispatch()

skill_auto_dispatch(task_id) {
  1. Load task metadata
  2. Check task.labels for category hints
  3. Check task.title for keyword matches
  4. Check task.type for protocol mapping
  5. Return skill name (protocol identifier)
}

skill_dispatch_by_keywords()

skill_dispatch_by_keywords(text) {
  for pattern in dispatch_matrix.by_keyword:
    if text matches pattern:
      return dispatch_matrix.by_keyword[pattern]
  return "ct-task-executor"  # Default
}

skill_prepare_spawn()

skill_prepare_spawn(skill_name, task_id) {
  1. Load base protocol
  2. Load skill SKILL.md
  3. Read conditional protocol (if exists)
  4. Resolve ALL tokens:
     - TASK_ID, EPIC_ID, DATE
     - OUTPUT_DIR, MANIFEST_PATH
     - SESSION_ID
  5. Compose final prompt
  6. Return JSON with:
     - taskId, epicId, date
     - prompt: fully-resolved content
     - tokenResolution.fullyResolved: true/false
}

Protocol Types

CLEO defines 7 standard protocols for subagent work:
ProtocolPurposeSkill
researchInformation gatheringct-research-agent
decompositionEpic/task breakdownct-epic-architect
implementationCode creationct-task-executor
specificationRFC/spec writingct-spec-writer
contributionPR/commit workflowct-task-executor
consensusMulti-perspective validationct-validator
releaseVersion/deploy workflowct-dev-workflow

Subagent Output Requirements

All subagents MUST follow RFC 2119 output protocol:
IDRuleCompliance
OUT-001MUST write to {{OUTPUT_DIR}}/{{DATE}}_{{TOPIC_SLUG}}.mdRequired
OUT-002MUST append ONE line to {{MANIFEST_PATH}}Required
OUT-003MUST return ONLY: “Research complete. See MANIFEST.jsonl”Required
OUT-004MUST NOT return research content in responseRequired

Manifest Entry Format

{"id":"topic-slug-2026-01-27","file":"2026-01-27_topic-slug.md","title":"Title","date":"2026-01-27","status":"complete","topics":["topic1"],"key_findings":["Finding 1","Finding 2"],"actionable":true,"needs_followup":["T1235"],"linked_tasks":["T1234"]}
Manifest entries MUST be single-line JSON (no pretty-printing) to support efficient line-by-line reading.

Skill Taxonomy

Skills are organized in a virtual hierarchy via manifest.json:
┌─────────────────────────────────────────────────────────────┐
│                    SKILL TAXONOMY                           │
│                  (virtual hierarchy)                        │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  skills[].tier:   0 | 1 | 2 | 3                            │
│  skills[].tags:   ["research", "documentation", ...]       │
│                                                             │
│  get_skills_by_category("documentation")                   │
│    → searches .tags[] for "documentation"                   │
│    → returns: ct-documentor, ct-docs-lookup, ct-docs-write │
│                                                             │
│  skill_list_by_tier(2)                                      │
│    → searches .tier == 2                                    │
│    → returns: ct-research-agent, ct-task-executor, ...     │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Tier Definitions

TierNameCountPurpose
0Orchestration1HITL entry, workflow coordination
1Planning1Decomposition, architecture
2Execution7Implementation, research, testing
3Support6Documentation, meta-skills

Filesystem Structure

skills/
├── ct-orchestrator/SKILL.md        ← Tier 0
├── ct-epic-architect/SKILL.md      ← Tier 1
├── ct-research-agent/SKILL.md      ← Tier 2
├── ct-task-executor/SKILL.md       ← Tier 2
├── ct-spec-writer/SKILL.md         ← Tier 2
├── ct-test-writer-bats/SKILL.md    ← Tier 2
├── ct-library-implementer-bash/    ← Tier 2
├── ct-validator/SKILL.md           ← Tier 2
├── ct-dev-workflow/SKILL.md        ← Tier 2
├── ct-documentor/SKILL.md          ← Tier 3
├── ct-docs-lookup/SKILL.md         ← Tier 3
├── ct-docs-write/SKILL.md          ← Tier 3
├── ct-docs-review/SKILL.md         ← Tier 3
├── ct-skill-creator/SKILL.md       ← Tier 3
├── ct-skill-lookup/SKILL.md        ← Tier 3
├── _shared/                        ← Shared protocols
│   ├── task-system-integration.md
│   └── subagent-protocol-base.md
├── mp/                             ← SkillsMP external skills
│   └── manifest.json
└── manifest.json                   ← SOURCE OF TRUTH

Debugging Dispatch

Check Dispatch Decision

# What skill would be selected for a task?
source lib/skill-dispatch.sh
skill=$(skill_auto_dispatch "T1234")
echo "Selected: $skill"

Verify Token Resolution

# Check if tokens are fully resolved
context=$(skill_prepare_spawn "ct-research-agent" "T1234")
echo "$context" | jq '.tokenResolution'

Inspect Protocol Composition

# See the full composed prompt
cleo orchestrator spawn T1234 --json | jq '.prompt'

Anti-Patterns

PatternProblemSolution
Spawning ct-research-agent directlyWrong agent typeSpawn cleo-subagent with research protocol
Returning full contentBloats orchestrator contextReturn only summary message
Unresolved tokens in promptSubagent can’t executeCheck tokenResolution.fullyResolved
Reading full research filesContext overflowRead manifest summaries only
Spawning without dependency checkOut-of-order executionRun cleo deps before spawn