---
name: orchestrate
description: "Decompose a multi-capability request, query the skill+role index, and either invoke a single skill yourself or assemble a Paperclip team. Use when one tool isn't enough."
category: meta
tags: [orchestration, multi-agent, planning, routing]
keywords: [orchestrator, swarm, team, decompose, plan, route, delegate, hire]
related: [paperclip]
metadata:
  minion:
    emoji: "🎼"
    requires:
      bins: [bash, jq, curl]
      config: [paperclip credentials at ~/.minion/credentials/<agent-id>/paperclip.env]
---

# orchestrate

You are about to handle a request that **may** require more than one capability. Your job is to either solve it yourself with one skill, or assemble a small team via Paperclip and let it do the work. **Never spawn a team for something a single skill could solve.**

## Decision flow

```
incoming request
      │
      ▼
[1] read skills.index.json + roles.index.json  ← see RECIPES § Read indexes
      │
      ▼
[2] is exactly ONE skill the obvious answer?
      ├── yes → invoke that skill directly. STOP.
      └── no, or ambiguous → continue
      │
      ▼
[3] does the request span 2+ capabilities OR multi-step state?
      ├── no → reply asking the user to narrow it. STOP.
      └── yes → continue
      │
      ▼
[4] design a team
      • pick 1-3 ROLES from the role library that cover the capabilities
      • prefer roles whose required_skills intersect the request
      • smaller team > bigger team (cost, latency, coordination overhead)
      │
      ▼
[5] hire roles into Paperclip → fan out sub-issues → poll → synthesize
      ← see RECIPES § Hire team, § Poll, § Synthesize
      │
      ▼
[6] return result + Paperclip parent-issue link as audit trail
```

## When NOT to use this skill

- The request is a single tool call (e.g. "send a slack message", "what's the weather"). Just call the tool.
- The user is having a conversation. Conversation is not a team.
- The request is already in a Paperclip issue you're working on. You're already inside the team — don't recurse.

## RECIPES

All recipes assume `paperclip.env` is already sourced for your bot identity:
```bash
source ~/.minion/credentials/<your-agent-id>/paperclip.env
# exports: PAPERCLIP_API_URL, PAPERCLIP_API_KEY, PAPERCLIP_COMPANY_ID
```

If it isn't sourced, you can't talk to Paperclip. Fall back to single-skill mode and tell the user.

### § Read indexes

```bash
# What skills exist + their categories?
bash ~/repos/minion-ai/scripts/skills/skills-query.sh stats
bash ~/repos/minion-ai/scripts/skills/skills-query.sh categories

# Find skills relevant to a query
bash ~/repos/minion-ai/scripts/skills/skills-query.sh search "<keyword>"

# Find skills in a category
bash ~/repos/minion-ai/scripts/skills/skills-query.sh list --category=<auth|comms|dev|data|media|infra|meta|lifestyle>

# Look at one skill in detail
bash ~/repos/minion-ai/scripts/skills/skills-query.sh get <slug>

# What roles are available?
bash ~/repos/minion-ai/scripts/skills/skills-query.sh roles list

# Which roles include a given skill?
bash ~/repos/minion-ai/scripts/skills/skills-query.sh roles find-for-skill <slug>

# What skills will I get if I pick this role?
bash ~/repos/minion-ai/scripts/skills/skills-query.sh roles skills-for <role-id>
```

If the indexes aren't there, run `bash ~/repos/minion-ai/scripts/skills/skills-index-build.sh` to regenerate. Otherwise tell the user the orchestrator can't see the catalog and degrade to single-skill mode.

### § Hire team

Paperclip uses Issues as the workflow primitive. Pattern:

1. Create one **parent issue** that describes the user request.
2. For each role in the team: create a **child issue** assigned to a Paperclip agent that has been hired with that role's skills + prompt template.

```bash
# Read the role record (you'll need its prompt_template + skills)
ROLE_ID="developer"
jq --arg id "$ROLE_ID" '.roles[] | select(.id == $id)' ~/.minion/roles.index.json

# Create the parent issue
PARENT=$(curl -sS -X POST \
  -H "Authorization: Bearer $PAPERCLIP_API_KEY" \
  -H "Content-Type: application/json" \
  "$PAPERCLIP_API_URL/api/v1/companies/$PAPERCLIP_COMPANY_ID/issues" \
  -d "$(jq -n \
    --arg t "Orchestrator: <one-line summary>" \
    --arg b "Request:\n<full user request>\n\nTeam:\n- developer (handles X)\n- researcher (handles Y)" \
    '{title: $t, body: $b, status: "open", priority: "P2"}')" \
  | jq -r .id)

echo "Parent issue: $PAPERCLIP_API_URL/issues/$PARENT"

# For each role: create a child issue (parentId set)
curl -sS -X POST \
  -H "Authorization: Bearer $PAPERCLIP_API_KEY" \
  -H "Content-Type: application/json" \
  "$PAPERCLIP_API_URL/api/v1/companies/$PAPERCLIP_COMPANY_ID/issues" \
  -d "$(jq -n \
    --arg t "[role:$ROLE_ID] <task slice>" \
    --arg b "<role-specific prompt + slice of user request>" \
    --arg p "$PARENT" \
    '{title: $t, body: $b, parentId: $p, status: "open", priority: "P2"}')"
```

Note: which Paperclip agent picks up each child issue depends on the company's routing config. The role's `default_model` and `prompt_template` are advisory hints embedded in the issue body — the actual agent assignment is Paperclip's call. If the company doesn't have an agent that fits a role, that's a routing gap; surface it to the user instead of forcing.

### § Poll

```bash
# Watch the parent — when all children resolved, you have your answer
while true; do
  RESP=$(curl -sS -H "Authorization: Bearer $PAPERCLIP_API_KEY" \
    "$PAPERCLIP_API_URL/api/v1/companies/$PAPERCLIP_COMPANY_ID/issues/$PARENT")
  STATUS=$(echo "$RESP" | jq -r .status)
  CHILDREN_OPEN=$(echo "$RESP" | jq '[.children[]? | select(.status != "closed")] | length')
  echo "$(date +%H:%M:%S) parent=$STATUS open-children=$CHILDREN_OPEN"
  [ "$CHILDREN_OPEN" -eq 0 ] && break
  sleep 30
done
```

Cap polling at 10 minutes. If still open, surface a partial-result with the parent-issue URL and let the user decide.

### § Synthesize

Once all child issues are closed:

```bash
# Pull each child's resolution comment
for CHILD_ID in $(curl -sS -H "Authorization: Bearer $PAPERCLIP_API_KEY" \
    "$PAPERCLIP_API_URL/api/v1/companies/$PAPERCLIP_COMPANY_ID/issues/$PARENT" \
    | jq -r '.children[].id'); do
  echo "=== child $CHILD_ID ==="
  curl -sS -H "Authorization: Bearer $PAPERCLIP_API_KEY" \
    "$PAPERCLIP_API_URL/api/v1/companies/$PAPERCLIP_COMPANY_ID/issues/$CHILD_ID/comments" \
    | jq -r '.[].body'
done
```

Then:
1. Read each child's comments
2. Compose a single user-facing reply that integrates the findings
3. Include the parent-issue URL: `$PAPERCLIP_API_URL/issues/$PARENT` — this is the audit trail
4. Don't dump raw comment text at the user; synthesize

## Worked examples

### Single-skill (don't orchestrate)

> "What's the weather in Lima?"

→ `weather` skill alone. No team. No Paperclip issue.

### Single-skill ambiguous (clarify, don't orchestrate)

> "Help me with auth"

→ Ask: "auth for what — 1Password vault, GitHub login, gateway tokens?". Don't assemble a team for a vague request.

### Two-capability (small team)

> "Find PRs that reference issue #42 in NikolasP98/minion-ai and post a summary in #pr-watch on Slack"

→ Two capabilities: GitHub query + Slack post. Roles: `developer` (gh-issues) + `comms-relay` (slack). Parent issue + 2 children.

### Multi-step research

> "Pull the last 3 podcast episodes from feed X, summarize each, save to Obsidian, and send me a digest in Slack"

→ Roles: `researcher` (summarize, obsidian) + `comms-relay` (slack). Parent + 2 children. Researcher does the heavy lift; relay just delivers.

## Operator notes

- Always include a parent-issue URL in your reply — that's the audit trail Paperclip provides.
- Hard cap: 3 roles per team. More than that means the request needs decomposing into separate orchestrations, not one giant team.
- If you can't find a role that fits, fall back to assembling a custom one-off agent with raw skills (use the `paperclip` skill's create-agent recipe). Note this in the parent issue body.
- Polling for 10 minutes max. Beyond that, surface what's done + the issue link.
- This skill assumes the Paperclip company already exists (FACES SCULPTORS for now). Multi-company orchestration is out of scope until a future phase adds company-routing.
