Files
agent0/scripts/pull-agent-identity.py
T
gitprov 8e97cbc97a Configure all agents for local inference via festinger
- All agents now use lm_studio provider → http://festinger:11434
- ctx_length set to 32768 for Omega13 (128GB RAM); reduce for smaller machines
- Model: qwen2.5-7b-instruct (update to larger model on Omega13)
- Each agent has a unique A0_PERSISTENT_RUNTIME_ID for stable mcp_server_token
- agent_profile=agent0 and mcp_server_enabled=true set in all settings.json
- agents/agent0/prompts/ placeholder created for pull-on-start persona override
- pull-agent-identity.py now writes to usr/agents/agent0/prompts/ (correct override path)
- festinger: agent_frameworks table auto-seeded on startup with all 5 agents
- festinger: num_ctx injection, agent_frameworks CRUD + admin UI, /chat endpoint
- festinger: removed debug system_prompt logging

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 13:00:07 +02:00

115 lines
4.4 KiB
Python

#!/usr/bin/env python3
"""
pull-agent-identity.py
Pulls agent identity from the gnommoweb Content API and writes the appropriate
persona files for the configured agent type.
Runs as an init container before the main agent process starts.
Exits 0 even on failure so the agent container still starts — the previous
identity file (if any) remains in place.
Environment variables:
AGENT_ID - gnommoweb agent ID (integer, required)
AGENT_TYPE - agent type: 'agent0' | 'hermes' (required)
CONTENT_API_URL - gnommoweb base URL, e.g. https://glitch.university
CONTENT_API_KEY - bearer token for the gnommoweb Content API
"""
import os
import sys
import json
import urllib.request
import urllib.error
AGENT_ID = os.environ.get('AGENT_ID', '').strip()
AGENT_TYPE = os.environ.get('AGENT_TYPE', '').strip()
CONTENT_API_URL = os.environ.get('CONTENT_API_URL', '').strip().rstrip('/')
CONTENT_API_KEY = os.environ.get('CONTENT_API_KEY', '').strip()
TAG = '[pull-agent-identity]'
# All output goes to stdout so it's always visible in docker compose logs.
def log(msg):
print(f'{TAG} {msg}', flush=True)
def bail(msg):
"""Log and exit 0 so the main container still starts."""
log(f'SKIP: {msg}')
sys.exit(0)
def fail(msg):
"""Log a failure and exit 0 so the main container still starts."""
log(f'FAILED: {msg}')
sys.exit(0)
# ── Validate env ──────────────────────────────────────────────────────────────
if not AGENT_ID:
bail('AGENT_ID not set')
if not AGENT_TYPE:
bail('AGENT_TYPE not set')
if not CONTENT_API_URL:
bail('CONTENT_API_URL not set')
if not CONTENT_API_KEY:
bail('CONTENT_API_KEY not set')
# ── Fetch identity from gnommoweb ─────────────────────────────────────────────
url = f'{CONTENT_API_URL}/api/content/agents/{AGENT_ID}'
log(f'Fetching identity for agent {AGENT_ID} (type={AGENT_TYPE}) from {url}')
req = urllib.request.Request(
url,
headers={'Authorization': f'Bearer {CONTENT_API_KEY}'},
)
try:
with urllib.request.urlopen(req, timeout=15) as resp:
data = json.load(resp)
except urllib.error.HTTPError as e:
fail(f'HTTP {e.code} from {url}: {e.read().decode()[:300]}')
except Exception as e:
fail(f'Request error ({url}): {e}')
agent = data.get('agent')
if not agent:
fail(f'Response from {url} contained no "agent" key')
log(f'Received identity — name={agent.get("name", "?")!r}')
# ── Build identity markdown ───────────────────────────────────────────────────
def build_identity_markdown(a):
parts = [f'# {a["name"]}']
if a.get('role'): parts.append(f'**Role:** {a["role"]}')
if a.get('from_name'): parts.append(f'**Known as:** {a["from_name"]}')
if a.get('identity_document'): parts.append(f'\n## Background\n{a["identity_document"]}')
if a.get('job_description'): parts.append(f'\n## Job Description\n{a["job_description"]}')
if a.get('guardrails'): parts.append(f'\n## Guardrails\n{a["guardrails"]}')
if a.get('best_practices'): parts.append(f'\n## Best Practices\n{a["best_practices"]}')
return '\n'.join(parts) + '\n'
# ── Write agent-type-specific files ──────────────────────────────────────────
if AGENT_TYPE == 'agent0':
# Agent Zero uses profile 'agent0' which resolves prompts from usr/agents/agent0/prompts/
# before falling back to usr/prompts/ or the built-in agents/agent0/prompts/.
# Writing here ensures our identity overrides the default "I am Agent Zero" role.
prompts_dir = '/a0/usr/agents/agent0/prompts'
prompt_file = os.path.join(prompts_dir, 'agent.system.main.role.md')
os.makedirs(prompts_dir, exist_ok=True)
content = build_identity_markdown(agent)
with open(prompt_file, 'w') as f:
f.write(content)
sections = [k for k in ('role', 'from_name', 'identity_document', 'job_description', 'guardrails', 'best_practices') if agent.get(k)]
log(f'OK — wrote {len(content)} chars to {prompt_file} (sections: {", ".join(sections) or "name only"})')
else:
log(f'WARNING: no handler for AGENT_TYPE={AGENT_TYPE!r} — nothing written')