feat: add Atomizer HQ multi-agent cluster infrastructure
- 8-agent OpenClaw cluster (Manager, Tech-Lead, Secretary, Auditor, Optimizer, Study-Builder, NX-Expert, Webster) - Orchestration engine: orchestrate.py (sync delegation + handoffs) - Workflow engine: YAML-defined multi-step pipelines - Agent workspaces: SOUL.md, AGENTS.md, MEMORY.md per agent - Shared skills: delegate, orchestrate, atomizer-protocols - Capability registry (AGENTS_REGISTRY.json) - Cluster management: cluster.sh, systemd template - All secrets replaced with env var references
This commit is contained in:
68
hq/workspaces/shared/skills/delegate/SKILL.md
Normal file
68
hq/workspaces/shared/skills/delegate/SKILL.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# Delegate Task to Another Agent
|
||||
|
||||
Sends a task to another Atomizer agent via the OpenClaw Hooks API. The target agent processes the task in an isolated session and optionally delivers the response to Discord.
|
||||
|
||||
## When to Use
|
||||
|
||||
- You need another agent to perform a task (research, analysis, NX work, etc.)
|
||||
- You want to assign work and get a response in a Discord channel
|
||||
- Cross-agent orchestration
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
bash /home/papa/atomizer/workspaces/shared/skills/delegate/delegate.sh <agent> "<instruction>" [options]
|
||||
```
|
||||
|
||||
### Agents
|
||||
|
||||
| Agent | Specialty |
|
||||
|-------|-----------|
|
||||
| `manager` | Orchestration, project oversight |
|
||||
| `tech-lead` | Technical decisions, FEA review |
|
||||
| `secretary` | Meeting notes, admin, status updates |
|
||||
| `auditor` | Quality checks, compliance review |
|
||||
| `optimizer` | Optimization setup, parameter studies |
|
||||
| `study-builder` | Study configuration, DOE |
|
||||
| `nx-expert` | NX/Simcenter operations |
|
||||
| `webster` | Web research, literature search |
|
||||
|
||||
### Options
|
||||
|
||||
- `--channel <discord-channel-id>` — Route response to a specific Discord channel
|
||||
- `--deliver` / `--no-deliver` — Whether to post response to Discord (default: deliver)
|
||||
|
||||
### Examples
|
||||
|
||||
```bash
|
||||
# Ask Webster to research something
|
||||
bash /home/papa/atomizer/workspaces/shared/skills/delegate/delegate.sh webster "Find the CTE of Zerodur Class 0 between 20-40°C"
|
||||
|
||||
# Assign NX work with channel routing
|
||||
bash /home/papa/atomizer/workspaces/shared/skills/delegate/delegate.sh nx-expert "Create mesh convergence study for M2 mirror" --channel C0AEJV13TEU
|
||||
|
||||
# Ask auditor to review without posting to Discord
|
||||
bash /home/papa/atomizer/workspaces/shared/skills/delegate/delegate.sh auditor "Review the thermal analysis assumptions" --no-deliver
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
1. Looks up the target agent's port from the cluster port map
|
||||
2. Checks if the target agent is running
|
||||
3. Sends a `POST /hooks/agent` request to the target's OpenClaw instance
|
||||
4. Target agent processes the task in an isolated session
|
||||
5. Response is delivered to Discord if `--deliver` is set
|
||||
|
||||
## Response
|
||||
|
||||
The script outputs:
|
||||
- ✅ confirmation with run ID on success
|
||||
- ❌ error message with HTTP code on failure
|
||||
|
||||
The delegated task runs **asynchronously** — you won't get the result inline. The target agent will respond in Discord.
|
||||
|
||||
## Notes
|
||||
|
||||
- Tasks are fire-and-forget. Monitor the Discord channel for the response.
|
||||
- The target agent sees the message as a hook trigger, not a Discord message.
|
||||
- For complex multi-step workflows, delegate one step at a time.
|
||||
118
hq/workspaces/shared/skills/delegate/delegate.sh
Executable file
118
hq/workspaces/shared/skills/delegate/delegate.sh
Executable file
@@ -0,0 +1,118 @@
|
||||
#!/usr/bin/env bash
|
||||
# delegate.sh — Send a task to another Atomizer agent via OpenClaw Hooks API
|
||||
# Usage: delegate.sh <agent> <message> [--channel <discord-channel-id>] [--deliver] [--wait]
|
||||
#
|
||||
# Examples:
|
||||
# delegate.sh webster "Find density of Ti-6Al-4V"
|
||||
# delegate.sh nx-expert "Mesh the M2 mirror" --channel C0AEJV13TEU --deliver
|
||||
# delegate.sh tech-lead "Review optimization results" --deliver
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# --- Port Map (from cluster config) ---
|
||||
declare -A PORT_MAP=(
|
||||
[manager]=18800
|
||||
[tech-lead]=18804
|
||||
[secretary]=18808
|
||||
[auditor]=18812
|
||||
[optimizer]=18816
|
||||
[study-builder]=18820
|
||||
[nx-expert]=18824
|
||||
[webster]=18828
|
||||
)
|
||||
|
||||
# --- Config ---
|
||||
TOKEN="${GATEWAY_TOKEN}"
|
||||
HOST="127.0.0.1"
|
||||
|
||||
# --- Parse args ---
|
||||
if [[ $# -lt 2 ]]; then
|
||||
echo "Usage: delegate.sh <agent> <message> [--channel <id>] [--deliver] [--wait]"
|
||||
echo ""
|
||||
echo "Agents: ${!PORT_MAP[*]}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
AGENT="$1"
|
||||
MESSAGE="$2"
|
||||
shift 2
|
||||
|
||||
CHANNEL=""
|
||||
DELIVER="true"
|
||||
WAIT=""
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--channel) CHANNEL="$2"; shift 2 ;;
|
||||
--deliver) DELIVER="true"; shift ;;
|
||||
--no-deliver) DELIVER="false"; shift ;;
|
||||
--wait) WAIT="true"; shift ;;
|
||||
*) echo "Unknown option: $1"; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# --- Validate agent ---
|
||||
PORT="${PORT_MAP[$AGENT]:-}"
|
||||
if [[ -z "$PORT" ]]; then
|
||||
echo "❌ Unknown agent: $AGENT"
|
||||
echo "Available agents: ${!PORT_MAP[*]}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Don't delegate to yourself ---
|
||||
SELF_PORT="${ATOMIZER_SELF_PORT:-}"
|
||||
if [[ -n "$SELF_PORT" && "$PORT" == "$SELF_PORT" ]]; then
|
||||
echo "❌ Cannot delegate to yourself"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Check if target is running ---
|
||||
if ! curl -sf "http://$HOST:$PORT/health" > /dev/null 2>&1; then
|
||||
# Try a simple connection check instead
|
||||
if ! timeout 2 bash -c "echo > /dev/tcp/$HOST/$PORT" 2>/dev/null; then
|
||||
echo "❌ Agent '$AGENT' is not running on port $PORT"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# --- Build payload ---
|
||||
PAYLOAD=$(cat <<EOF
|
||||
{
|
||||
"message": $(printf '%s' "$MESSAGE" | python3 -c "import json,sys; print(json.dumps(sys.stdin.read()))"),
|
||||
"name": "delegation",
|
||||
"sessionKey": "hook:delegation:$(date +%s)",
|
||||
"deliver": $DELIVER,
|
||||
"channel": "discord"
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
# Add Discord channel routing if specified
|
||||
if [[ -n "$CHANNEL" ]]; then
|
||||
PAYLOAD=$(echo "$PAYLOAD" | python3 -c "
|
||||
import json, sys
|
||||
d = json.load(sys.stdin)
|
||||
d['to'] = 'channel:$CHANNEL'
|
||||
print(json.dumps(d))
|
||||
")
|
||||
fi
|
||||
|
||||
# --- Send ---
|
||||
RESPONSE=$(curl -s -w "\n%{http_code}" -X POST "http://$HOST:$PORT/hooks/agent" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$PAYLOAD")
|
||||
|
||||
HTTP_CODE=$(echo "$RESPONSE" | tail -1)
|
||||
BODY=$(echo "$RESPONSE" | head -n -1)
|
||||
|
||||
if [[ "$HTTP_CODE" == "202" ]]; then
|
||||
RUN_ID=$(echo "$BODY" | python3 -c "import json,sys; print(json.loads(sys.stdin.read()).get('runId','unknown'))" 2>/dev/null || echo "unknown")
|
||||
echo "✅ Task delegated to $AGENT (port $PORT)"
|
||||
echo " Run ID: $RUN_ID"
|
||||
echo " Deliver to Discord: $DELIVER"
|
||||
else
|
||||
echo "❌ Delegation failed (HTTP $HTTP_CODE)"
|
||||
echo " Response: $BODY"
|
||||
exit 1
|
||||
fi
|
||||
Reference in New Issue
Block a user