feat(agent-zero): uvicorn A2A server calling LiteLLM directly
CI / validate (pull_request) Failing after 1s

This commit is contained in:
Abiba (pi)
2026-06-27 18:44:56 +00:00
parent 1cf6c2f806
commit 4db655d4f9
@@ -1,24 +1,24 @@
"""A2A Agent for kagentz — processes messages via Agent Zero core directly.""" """A2A agent for kagentz — uvicorn-based, calls LiteLLM for responses."""
import sys, os, asyncio, json, uuid, time import os, json, uuid, threading, asyncio
sys.path.insert(0, "/a0")
os.environ["A2A_TOKEN"] = "8zNgdOEXzYxjQvTl"
import uvicorn import uvicorn
from fastapi import FastAPI, Request from fastapi import FastAPI, Request
from agent import AgentContext, UserMessage, AgentContextType from fastapi.responses import JSONResponse
import httpx
app = FastAPI() app = FastAPI()
AGENT_TOKEN = os.environ["A2A_TOKEN"] task_results = {}
LITELLM_URL = "https://litellm.sysloggh.net/v1"
LITELLM_KEY = "sk-U_ydi3B-wfGU-_xESkoU1Q"
LITELLM_MODEL = "syslog-auto"
@app.get("/.well-known/agent.json") @app.get("/.well-known/agent.json")
async def agent_card(): async def agent_card():
return { return {
"name": "kagentz", "name": "kagentz",
"version": "1.0.0", "version": "1.0.0",
"description": "Agent Zero instance managed via Zulip", "description": "Agent Zero on CT 105 via Zulip + LiteLLM",
"capabilities": {"a2a": {"version": "1.0", "authentication": ["bearer"]}}, "capabilities": {"a2a": {"version": "1.0"}},
"skills": [{"id": "chat", "name": "Chat", "description": "General conversation via Zulip"}], "skills": [{"id": "chat", "name": "Chat"}],
} }
@app.post("/a2a") @app.post("/a2a")
@@ -31,17 +31,13 @@ async def a2a_endpoint(request: Request):
msg = params.get("message", {}) msg = params.get("message", {})
parts = msg.get("parts", []) parts = msg.get("parts", [])
text = " ".join(p.get("text", "") for p in parts if isinstance(p, dict)) text = " ".join(p.get("text", "") for p in parts if isinstance(p, dict))
task_id = f"az-{uuid.uuid4().hex[:12]}" task_id = f"az-{uuid.uuid4().hex[:12]}"
asyncio.create_task(process_via_agent_zero(task_id, text)) asyncio.create_task(call_litellm(task_id, text))
return {"jsonrpc": "2.0", "result": {"id": task_id, "status": {"state": "working"}}} return {"jsonrpc": "2.0", "result": {"id": task_id, "status": {"state": "working"}}}
elif method == "tasks/get": elif method == "tasks/get":
params = body.get("params", {}) task_id = body.get("params", {}).get("id", "")
task_id = params.get("id", "")
status, result = task_results.get(task_id, ("pending", None)) status, result = task_results.get(task_id, ("pending", None))
resp = {"jsonrpc": "2.0", "result": {"id": task_id, "status": {"state": status}}} resp = {"jsonrpc": "2.0", "result": {"id": task_id, "status": {"state": status}}}
if status == "completed" and result: if status == "completed" and result:
resp["result"]["history"] = [ resp["result"]["history"] = [
@@ -49,44 +45,31 @@ async def a2a_endpoint(request: Request):
{"role": "assistant", "parts": [{"text": result.get("output", "")}]}, {"role": "assistant", "parts": [{"text": result.get("output", "")}]},
] ]
elif status == "failed": elif status == "failed":
resp["result"]["status"]["message"] = {"text": str(result or "Unknown error")} resp["result"]["status"]["message"] = {"text": str(result)}
return resp return resp
return {"jsonrpc": "2.0", "error": {"code": -32601, "message": "Method not found"}} return {"jsonrpc": "2.0", "error": {"code": -32601, "message": "Method not found"}}
task_results = {} async def call_litellm(task_id, message):
async def process_via_agent_zero(task_id: str, message: str):
"""Process a message through Agent Zero's core."""
try: try:
# Create a new context and send the message async with httpx.AsyncClient(timeout=120.0) as client:
ctx = AgentContext.get(uuid.uuid4().hex) resp = await client.post(
f"{LITELLM_URL}/chat/completions",
# Run in executor to avoid blocking the event loop headers={"Authorization": f"Bearer {LITELLM_KEY}", "Content-Type": "application/json"},
loop = asyncio.get_event_loop() json={
"model": LITELLM_MODEL,
def _run(): "messages": [
try: {"role": "system", "content": "You are kagentz, an Agent Zero instance on CT 105. You communicate via Zulip. Keep responses concise."},
# Send user message and get response {"role": "user", "content": message},
msg = UserMessage(text=message, context=ctx) ],
result = ctx.agent.handle_message(msg) "max_tokens": 2000,
},
# Extract text response )
if hasattr(result, 'content'): if resp.is_success:
output = result.content output = resp.json()["choices"][0]["message"]["content"]
elif isinstance(result, str): task_results[task_id] = ("completed", {"input": message, "output": output})
output = result else:
else: task_results[task_id] = ("failed", f"HTTP {resp.status_code}")
output = str(result)
return output
except Exception as e:
return f"Error: {e}"
output = await loop.run_in_executor(None, _run)
task_results[task_id] = ("completed", {"input": message, "output": output})
except Exception as e: except Exception as e:
task_results[task_id] = ("failed", str(e)) task_results[task_id] = ("failed", str(e))