Files
openclaw/skills/multi-agent/spawn.py
Clawd Bot ca9b510922 chore: align with upstream openclaw/openclaw and overlay local additions
- Reset master to upstream/main (16,697 commits)
- Overlay 2,271 local-only files (skills, tools, workspace, configs, apps)
- Restore IDENTITY.md and USER.md templates
- Build verified, gateway running, Discord working

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 07:40:46 +01:00

132 lines
4.2 KiB
Python

#!/usr/bin/env python3
"""
Multi-Agent Spawner - Spawn any agent type via Gateway API
Bypasses sessions_spawn tool limitations
"""
import requests
import json
import argparse
import sys
import os
GATEWAY_URL = os.environ.get('OPENCLAW_GATEWAY_URL', 'https://localhost:18789')
GATEWAY_TOKEN = os.environ.get('OPENCLAW_GATEWAY_TOKEN', '916117a24ae61a926536bf992e38847421e53d16fb12ab73')
def spawn_agent(agent_id, task, label=None, timeout=3600, model=None, thinking='low', deliver=False):
"""
Spawn an isolated agent session via Gateway API
Args:
agent_id: Agent ID to spawn (gemini-3-flash, gpt5-mini, sonnet, etc.)
task: Task message/prompt for the agent
label: Optional session label
timeout: Timeout in seconds (default 3600 = 1 hour)
model: Override model (optional)
thinking: Thinking level (low/medium/high)
deliver: Deliver result to channel
Returns:
dict with sessionKey, runId, status
"""
# Build payload
payload = {
'agentId': agent_id,
'task': task,
'runTimeoutSeconds': timeout,
'thinking': thinking,
'deliver': deliver
}
if label:
payload['label'] = label
if model:
payload['model'] = model
# Call Gateway API directly (disable SSL verification for self-signed cert)
response = requests.post(
f'{GATEWAY_URL}/sessions/spawn',
headers={
'Authorization': f'Bearer {GATEWAY_TOKEN}',
'Content-Type': 'application/json'
},
json=payload,
timeout=10,
verify=False # Self-signed cert
)
if response.status_code == 200:
result = response.json()
return {
'status': 'success',
'sessionKey': result.get('childSessionKey'),
'runId': result.get('runId'),
'agentId': agent_id,
'label': label,
'task': task[:100]
}
else:
return {
'status': 'error',
'code': response.status_code,
'error': response.text
}
def main():
parser = argparse.ArgumentParser(description='Spawn OpenClaw sub-agents')
parser.add_argument('--agent', required=True, help='Agent ID (gemini-3-flash, gpt5-mini, sonnet)')
parser.add_argument('--task', required=True, help='Task message/prompt')
parser.add_argument('--label', help='Session label')
parser.add_argument('--timeout', type=int, default=3600, help='Timeout in seconds')
parser.add_argument('--model', help='Override model')
parser.add_argument('--thinking', default='low', choices=['low', 'medium', 'high'])
parser.add_argument('--deliver', action='store_true', help='Deliver result to channel')
parser.add_argument('--assign-kanban', help='Auto-assign to Kanban task ID')
parser.add_argument('--json', action='store_true', help='Output JSON only')
args = parser.parse_args()
# Spawn agent
result = spawn_agent(
agent_id=args.agent,
task=args.task,
label=args.label,
timeout=args.timeout,
model=args.model,
thinking=args.thinking,
deliver=args.deliver
)
# Auto-assign to Kanban if requested
if result['status'] == 'success' and args.assign_kanban:
import subprocess
session_id = result['sessionKey'].split(':')[-1]
assignee = f"{args.agent}:{session_id[:8]}"
subprocess.run([
'python3', '/home/alex/kanban-board/kanban_helper.py',
'update', args.assign_kanban,
f'assignee={assignee}',
'status=in_progress'
], check=False)
# Output
if args.json:
print(json.dumps(result, indent=2))
else:
if result['status'] == 'success':
print(f"✅ Spawned {args.agent}")
print(f" Session: {result['sessionKey']}")
print(f" Run ID: {result['runId']}")
if args.assign_kanban:
print(f" Kanban: Assigned to task {args.assign_kanban}")
else:
print(f"❌ Failed to spawn agent")
print(f" Error: {result.get('error', 'Unknown')}")
sys.exit(1)
return result
if __name__ == '__main__':
main()