- 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>
132 lines
4.2 KiB
Python
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()
|