Files
OmniRoute/docs/i18n/de/src/lib/a2a/README.md
2026-04-06 18:11:09 -03:00

28 KiB
Raw Blame History

OmniRoute A2A Server (Deutsch)

🌐 Languages: 🇺🇸 English · 🇪🇸 es · 🇫🇷 fr · 🇩🇪 de · 🇮🇹 it · 🇷🇺 ru · 🇨🇳 zh-CN · 🇯🇵 ja · 🇰🇷 ko · 🇸🇦 ar · 🇮🇳 hi · 🇮🇳 in · 🇹🇭 th · 🇻🇳 vi · 🇮🇩 id · 🇲🇾 ms · 🇳🇱 nl · 🇵🇱 pl · 🇸🇪 sv · 🇳🇴 no · 🇩🇰 da · 🇫🇮 fi · 🇵🇹 pt · 🇷🇴 ro · 🇭🇺 hu · 🇧🇬 bg · 🇸🇰 sk · 🇺🇦 uk-UA · 🇮🇱 he · 🇵🇭 phi · 🇧🇷 pt-BR · 🇨🇿 cs · 🇹🇷 tr


Agent-to-Agent-Protokoll v0.3 Ermöglicht jedem KI-Agenten die Verwendung von OmniRoute als intelligenten Routing-Agenten über JSON-RPC 2.0.

Der A2A-Server stellt OmniRoute alserstklassigen Agentenzur Verfügung, den andere Agenten mithilfe des A2A-Protokolls entdecken, an den sie Aufgaben delegieren und mit dem sie zusammenarbeiten können.---

Architektur

┌──────────────────────────────────────────────────────────────────┐
│                    Orchestrator Agent                             │
│        (LangChain, CrewAI, AutoGen, Custom Agent)                │
└──────────────────────┬───────────────────────────────────────────┘
                       │  1. GET /.well-known/agent.json  (discover)
                       │  2. POST /a2a  (JSON-RPC 2.0)
                       ▼
┌──────────────────────────────────────────────────────────────────┐
│                     OmniRoute A2A Server                         │
│  ┌────────────────┐  ┌────────────────┐  ┌───────────────────┐  │
│  │  Task Manager  │  │  Skill Engine  │  │  SSE Streaming    │  │
│  │  (lifecycle)   │──│  (registry)    │──│  (real-time)      │  │
│  └────────────────┘  └────────┬───────┘  └───────────────────┘  │
│                               │                                  │
│  Skills:                      │                                  │
│    ├─ smart-routing ──────────┤  ┌────────────────────────────┐  │
│    └─ quota-management ───────┘  │  Routing Decision Logger   │  │
│                                  └────────────────────────────┘  │
└──────────────────────────────────────────────────────────────────┘
                       │
                       ▼  OmniRoute Gateway (internal)
              /v1/chat/completions, /api/combos, /api/usage/quota

Schnellstart

Agent Discovery

Jeder A2A-kompatible Agent stellt eineAgentenkarteunter „/.well-known/agent.json“ bereit:```bash curl http://localhost:20128/.well-known/agent.json


**Antwort:**```json
{
  "name": "OmniRoute",
  "description": "Intelligent AI gateway with auto-routing across 50+ providers",
  "url": "http://localhost:20128/a2a",
  "version": "1.8.1",
  "capabilities": {
    "streaming": true,
    "pushNotifications": false
  },
  "skills": [
    {
      "id": "smart-routing",
      "name": "Smart Routing",
      "description": "Routes prompts through OmniRoute intelligent pipeline",
      "tags": ["routing", "llm", "multi-provider", "cost-optimization"],
      "examples": [
        "Write a hello world in Python",
        "Explain quantum computing using the cheapest provider"
      ]
    },
    {
      "id": "quota-management",
      "name": "Quota Management",
      "description": "Natural-language queries about provider quotas",
      "tags": ["quota", "analytics", "cost"],
      "examples": [
        "Which provider has the most quota remaining?",
        "Suggest a free combo for coding"
      ]
    }
  ],
  "authentication": {
    "schemes": ["bearer"],
    "apiKeyHeader": "Authorization"
  }
}

JSON-RPC 2.0 Methods

message/send — Synchronous Execution

Senden Sie eine Nachricht an einen Skill und erhalten Sie die vollständige Antwort.```bash curl -X POST http://localhost:20128/a2a
-H "Content-Type: application/json"
-H "Authorization: Bearer YOUR_KEY"
-d '{ "jsonrpc": "2.0", "id": "1", "method": "message/send", "params": { "skill": "smart-routing", "messages": [{"role": "user", "content": "Write a Python hello world"}], "metadata": {"model": "auto", "combo": "fast-coding"} } }'


**Antwort:**```json
{
  "jsonrpc": "2.0",
  "id": "1",
  "result": {
    "task": { "id": "a1b2c3d4-...", "state": "completed" },
    "artifacts": [{ "type": "text", "content": "print('Hello, World!')" }],
    "metadata": {
      "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.0030)",
      "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
      "resilience_trace": [
        { "event": "primary_selected", "provider": "anthropic", "timestamp": "2026-03-04T..." }
      ],
      "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
    }
  }
}

message/stream — SSE Streaming

Identisch mit „message/send“, gibt aber vom Server gesendete Ereignisse für Echtzeit-Streaming zurück.```bash curl -N -X POST http://localhost:20128/a2a
-H "Content-Type: application/json"
-H "Authorization: Bearer YOUR_KEY"
-d '{ "jsonrpc": "2.0", "id": "1", "method": "message/stream", "params": { "skill": "smart-routing", "messages": [{"role": "user", "content": "Explain quantum computing"}] } }'


**SSE-Ereignisse:**```
data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"Quantum computing..."}}}

: heartbeat 2026-03-04T21:00:00Z

data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}

tasks/get — Query Task Status

curl -X POST http://localhost:20128/a2a \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_KEY" \
  -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'

tasks/cancel — Cancel a Running Task

curl -X POST http://localhost:20128/a2a \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_KEY" \
  -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'

Skills Reference

smart-routing

Leitet Eingabeaufforderungen mit vollständiger Beobachtbarkeit durch die intelligente Pipeline von OmniRoute weiter.

Parameter (in „Metadaten“):

Parameter Geben Sie ein Standard Beschreibung
„Modell“ Zeichenfolge "auto" Zielmodell (z. B. „claude-sonnet-4“, „gpt-4o“, „auto“)
„Kombination“ Zeichenfolge aktive Kombination Spezifische Kombination zum Weiterleiten durch
„Budget“ Nummer keine Maximale Kosten in USD für diese Anfrage
„Rolle“ Zeichenfolge keine Hinweis zur Aufgabenrolle: „Codierung“, „Überprüfung“, „Planung“, „Analyse“, „Debugging“, „Dokumentation“

Rücksendungen:

Feld Beschreibung
artifacts[].content Der LLM-Antworttext
metadata.routing_explanation Menschenlesbare Erklärung der Routing-Entscheidung
metadata.cost_envelope Geschätzte vs. tatsächliche Kosten mit Währung
metadata.resilience_trace Array von Ereignissen (primary_selected, fallback_needed usw.)
metadata.policy_verdict Ob die Anfrage zugelassen wurde und warum ### quota-management

Beantwortet Fragen zu Anbieterkontingenten in natürlicher Sprache.

Abfragetypen (abgeleitet aus dem Nachrichteninhalt):

Abfragemuster Antworttyp
Enthält „ranking“, „most quote“, „best“ Anbieter sortiert nach Restkontingent
Enthält „kostenlos“ und „empfehlen“ Listet kostenlose Kombinationen auf oder schlägt kostenlose Anbieter vor
Standard Vollständige Kontingentzusammenfassung mit Warnungen für Anbieter mit niedrigen Kontingenten ---

Task Lifecycle

submitted ──→ working ──→ completed
                       ──→ failed
              ──────────→ cancelled
Staat Beschreibung
eingereicht Aufgabe erstellt, zur Ausführung in die Warteschlange gestellt
„arbeiten“ Der Skill-Handler führt aus
„abgeschlossen“ Ausführung erfolgreich, Artefakte verfügbar
„fehlgeschlagen“ Ausführung fehlgeschlagen oder Aufgabe abgelaufen (TTL: 5 Min. Standard)
„abgesagt“ Vom Kunden über „Aufgaben/Abbrechen“ abgebrochen
  • Terminalzustände: „abgeschlossen“, „fehlgeschlagen“, „abgebrochen“ (keine weiteren Übergänge)
  • Abgelaufene Aufgaben im Status „Eingereicht“ oder „In Arbeit“ werden automatisch als „fehlgeschlagen“ markiert
  • Aufgaben werden nach 2× TTL im Garbage Collection gesammelt---

Client Examples

Python — Orchestrator Agent

"""
A2A Client — Python example.
Discovers OmniRoute agent, sends a task, and processes the result.
"""
import requests
import json

BASE_URL = "http://localhost:20128"
API_KEY = "your-api-key"
HEADERS = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {API_KEY}",
}

# 1. Discover agent capabilities
agent_card = requests.get(f"{BASE_URL}/.well-known/agent.json").json()
print(f"Agent: {agent_card['name']} v{agent_card['version']}")
print(f"Skills: {[s['id'] for s in agent_card['skills']]}")

# 2. Send a smart-routing task
response = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
    "jsonrpc": "2.0",
    "id": "task-1",
    "method": "message/send",
    "params": {
        "skill": "smart-routing",
        "messages": [{"role": "user", "content": "Write a Python quicksort implementation"}],
        "metadata": {
            "model": "auto",
            "combo": "fast-coding",
            "budget": 0.10,
        }
    }
})
result = response.json()["result"]
print(f"\n📝 Response: {result['artifacts'][0]['content'][:200]}...")
print(f"🔀 Routing: {result['metadata']['routing_explanation']}")
print(f"💰 Cost: ${result['metadata']['cost_envelope']['actual']}")
print(f"🛡️ Policy: {result['metadata']['policy_verdict']['reason']}")

# 3. Query quota status
quota_resp = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
    "jsonrpc": "2.0",
    "id": "task-2",
    "method": "message/send",
    "params": {
        "skill": "quota-management",
        "messages": [{"role": "user", "content": "Which provider has the most quota remaining?"}],
    }
})
quota_result = quota_resp.json()["result"]
print(f"\n📊 Quota: {quota_result['artifacts'][0]['content']}")

TypeScript — Multi-Agent Orchestrator

/**
 * A2A Client — TypeScript example.
 * Shows agent discovery, task delegation, and streaming.
 */

const BASE_URL = "http://localhost:20128";
const API_KEY = "your-api-key";

interface JsonRpcResponse<T = any> {
  jsonrpc: "2.0";
  id: string | number;
  result?: T;
  error?: { code: number; message: string };
}

async function a2aCall<T>(method: string, params: Record<string, any>): Promise<T> {
  const resp = await fetch(`${BASE_URL}/a2a`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${API_KEY}`,
    },
    body: JSON.stringify({
      jsonrpc: "2.0",
      id: `${method}-${Date.now()}`,
      method,
      params,
    }),
  });
  const json: JsonRpcResponse<T> = await resp.json();
  if (json.error) throw new Error(`[${json.error.code}] ${json.error.message}`);
  return json.result!;
}

// ── Agent Discovery ──
const agentCard = await fetch(`${BASE_URL}/.well-known/agent.json`).then((r) => r.json());
console.log(`Connected to: ${agentCard.name} (${agentCard.skills.length} skills)`);

// ── Smart Routing: Send a coding task ──
const routingResult = await a2aCall("message/send", {
  skill: "smart-routing",
  messages: [{ role: "user", content: "Implement a Redis cache wrapper in TypeScript" }],
  metadata: { model: "claude-sonnet-4", role: "coding" },
});
console.log("Response:", routingResult.artifacts[0].content);
console.log("Provider:", routingResult.metadata.routing_explanation);

// ── Quota Management: Find free alternatives ──
const quotaResult = await a2aCall("message/send", {
  skill: "quota-management",
  messages: [{ role: "user", content: "Suggest free combos for documentation" }],
});
console.log("Free combos:", quotaResult.artifacts[0].content);

// ── Streaming: Real-time response ──
const streamResp = await fetch(`${BASE_URL}/a2a`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: `Bearer ${API_KEY}`,
  },
  body: JSON.stringify({
    jsonrpc: "2.0",
    id: "stream-1",
    method: "message/stream",
    params: {
      skill: "smart-routing",
      messages: [{ role: "user", content: "Explain microservices architecture" }],
    },
  }),
});

const reader = streamResp.body!.getReader();
const decoder = new TextDecoder();
while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  const chunk = decoder.decode(value);
  for (const line of chunk.split("\n")) {
    if (line.startsWith("data: ")) {
      const event = JSON.parse(line.slice(6));
      if (event.params.chunk) {
        process.stdout.write(event.params.chunk.content);
      }
      if (event.params.task.state === "completed") {
        console.log("\n✅ Stream completed");
      }
    }
  }
}

Python — LangChain A2A Integration

"""
LangChain integration — Use OmniRoute A2A as a custom LLM.
"""
from langchain.llms.base import BaseLLM
from langchain.schema import LLMResult, Generation
import requests
from typing import List, Optional

class OmniRouteA2A(BaseLLM):
    base_url: str = "http://localhost:20128"
    api_key: str = ""
    model: str = "auto"
    combo: Optional[str] = None

    @property
    def _llm_type(self) -> str:
        return "omniroute-a2a"

    def _call(self, prompt: str, stop: Optional[List[str]] = None, **kwargs) -> str:
        response = requests.post(
            f"{self.base_url}/a2a",
            headers={
                "Content-Type": "application/json",
                "Authorization": f"Bearer {self.api_key}",
            },
            json={
                "jsonrpc": "2.0",
                "id": "langchain-1",
                "method": "message/send",
                "params": {
                    "skill": "smart-routing",
                    "messages": [{"role": "user", "content": prompt}],
                    "metadata": {
                        "model": self.model,
                        **({"combo": self.combo} if self.combo else {}),
                    },
                },
            },
        )
        result = response.json()["result"]
        return result["artifacts"][0]["content"]

    def _generate(self, prompts: List[str], stop=None, **kwargs) -> LLMResult:
        return LLMResult(
            generations=[[Generation(text=self._call(p, stop))] for p in prompts]
        )

# Usage
llm = OmniRouteA2A(
    base_url="http://localhost:20128",
    api_key="your-key",
    model="auto",
    combo="fast-coding",
)
result = llm("Write a Python function to merge two sorted lists")
print(result)

Go — A2A Client

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
)

const baseURL = "http://localhost:20128"
const apiKey = "your-api-key"

type JsonRpcRequest struct {
	Jsonrpc string      `json:"jsonrpc"`
	ID      string      `json:"id"`
	Method  string      `json:"method"`
	Params  interface{} `json:"params"`
}

type JsonRpcResponse struct {
	Jsonrpc string      `json:"jsonrpc"`
	ID      string      `json:"id"`
	Result  interface{} `json:"result"`
	Error   *struct {
		Code    int    `json:"code"`
		Message string `json:"message"`
	} `json:"error"`
}

func a2aCall(method string, params interface{}) (*JsonRpcResponse, error) {
	body, _ := json.Marshal(JsonRpcRequest{
		Jsonrpc: "2.0",
		ID:      "go-1",
		Method:  method,
		Params:  params,
	})

	req, _ := http.NewRequest("POST", baseURL+"/a2a", bytes.NewReader(body))
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "Bearer "+apiKey)

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	data, _ := io.ReadAll(resp.Body)

	var result JsonRpcResponse
	json.Unmarshal(data, &result)
	return &result, nil
}

func main() {
	// Discover agent
	resp, _ := http.Get(baseURL + "/.well-known/agent.json")
	defer resp.Body.Close()
	body, _ := io.ReadAll(resp.Body)
	fmt.Println("Agent Card:", string(body))

	// Send smart-routing task
	result, _ := a2aCall("message/send", map[string]interface{}{
		"skill":    "smart-routing",
		"messages": []map[string]string{{"role": "user", "content": "Hello from Go!"}},
		"metadata": map[string]interface{}{"model": "auto"},
	})
	out, _ := json.MarshalIndent(result.Result, "", "  ")
	fmt.Println("Result:", string(out))
}

Use Cases

🤖 Use Case 1: Multi-Agent Coding Pipeline

Ein Orchestrator-Agent delegiert die Codegenerierung an OmniRoute und übergibt die Ausgabe dann an einen Überprüfungsagenten.```python def coding_pipeline(task: str): # Step 1: Generate code via OmniRoute A2A code_result = a2a_send("smart-routing", [ {"role": "user", "content": f"Write production-quality code: {task}"} ], metadata={"model": "auto", "role": "coding"}) code = code_result["artifacts"][0]["content"]

# Step 2: Review the code via OmniRoute A2A (different model)
review_result = a2a_send("smart-routing", [
    {"role": "user", "content": f"Review this code for bugs and improvements:\n\n{code}"}
], metadata={"model": "auto", "role": "review"})
review = review_result["artifacts"][0]["content"]

# Step 3: Check costs
print(f"Code cost: ${code_result['metadata']['cost_envelope']['actual']}")
print(f"Review cost: ${review_result['metadata']['cost_envelope']['actual']}")

return {"code": code, "review": review}

### 💡 Use Case 2: Quota-Aware Agent Swarm

Mehrere Agenten teilen sich das Kontingent über OmniRoute und nutzen die Kontingentfähigkeit zur Koordinierung.```python
async def quota_aware_agent(agent_name: str, task: str):
    # Check quota before starting
    quota = a2a_send("quota-management", [
        {"role": "user", "content": "Which provider has the most quota remaining?"}
    ])
    print(f"[{agent_name}] {quota['artifacts'][0]['content']}")

    # Send request with budget constraint
    result = a2a_send("smart-routing", [
        {"role": "user", "content": task}
    ], metadata={"budget": 0.05})

    policy = result["metadata"]["policy_verdict"]
    if not policy["allowed"]:
        print(f"[{agent_name}] ⚠️ Budget exceeded: {policy['reason']}")
        # Fall back to free combo
        quota = a2a_send("quota-management", [
            {"role": "user", "content": "Suggest free combos"}
        ])
        print(f"[{agent_name}] Free alternatives: {quota['artifacts'][0]['content']}")

    return result

📊 Use Case 3: Real-Time Streaming Dashboard

Ein Überwachungsagent streamt Antworten und zeigt den Fortschritt in Echtzeit an.```typescript async function streamingDashboard(prompt: string) { const response = await fetch(${BASE_URL}/a2a, { method: "POST", headers: { "Content-Type": "application/json", Authorization: Bearer ${API_KEY} }, body: JSON.stringify({ jsonrpc: "2.0", id: "dash-1", method: "message/stream", params: { skill: "smart-routing", messages: [{ role: "user", content: prompt }] }, }), });

let totalChunks = 0; const reader = response.body!.getReader(); const decoder = new TextDecoder();

while (true) { const { done, value } = await reader.read(); if (done) break;

for (const line of decoder.decode(value).split("\n")) {
  if (line.startsWith("data: ")) {
    const event = JSON.parse(line.slice(6));
    const state = event.params.task.state;

    if (state === "working" && event.params.chunk) {
      totalChunks++;
      process.stdout.write(
        `\r[Chunk ${totalChunks}] ${event.params.chunk.content.slice(0, 50)}...`
      );
    }
    if (state === "completed") {
      const meta = event.params.metadata;
      console.log(
        `\n✅ Done | Cost: $${meta?.cost_envelope?.actual || 0} | Route: ${meta?.routing_explanation || "N/A"}`
      );
    }
    if (state === "failed") {
      console.error(`\n❌ Failed: ${event.params.metadata?.error}`);
    }
  }
}

} }


### 🔁 Use Case 4: Task Polling Pattern

Fragen Sie bei Aufgaben mit langer Laufzeit den Aufgabenstatus ab, anstatt synchron zu warten.```python
import time

def poll_task(task_id: str, timeout: int = 60):
    """Poll task status until completion or timeout."""
    start = time.time()
    while time.time() - start < timeout:
        result = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
            "jsonrpc": "2.0",
            "id": "poll-1",
            "method": "tasks/get",
            "params": {"taskId": task_id},
        }).json()

        task = result["result"]["task"]
        state = task["state"]
        print(f"  Task {task_id[:8]}... state={state}")

        if state in ("completed", "failed", "cancelled"):
            return task
        time.sleep(2)

    # Timeout — cancel the task
    requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
        "jsonrpc": "2.0",
        "id": "cancel-1",
        "method": "tasks/cancel",
        "params": {"taskId": task_id},
    })
    raise TimeoutError(f"Task {task_id} timed out after {timeout}s")

Error Codes

Code Konstante Bedeutung
-32700 Analysefehler (ungültiges JSON)
-32600 INVALID_REQUEST Ungültige JSON-RPC-Anfrage oder nicht autorisiert
-32601 METHOD_NOT_FOUND Unbekannte Methode oder Fähigkeit
-32602 INVALID_PARAMS Fehlende oder ungültige Parameter
-32603 INTERNER_FEHLER Fertigkeitsausführung fehlgeschlagen
-32001 TASK_NOT_FOUND Aufgaben-ID nicht gefunden
-32002 TASK_ALREADY_COMPLETED Eine abgeschlossene Aufgabe kann nicht geändert werden
-32003 „UNBEFUGLICH“ Ungültiger oder fehlender API-Schlüssel
-32004 „BUDGET_EXCEEDED“ Die Anfrage überschreitet das konfigurierte Budget
-32005 „PROVIDER_UNAVAILABLE“ Keine verfügbaren Anbieter ---

Authentication

Alle „/a2a“-Anfragen erfordern ein Bearer-Token über den „Authorization“-Header:``` Authorization: Bearer YOUR_OMNIROUTE_API_KEY


Wenn auf dem Server kein API-Schlüssel konfiguriert ist („OMNIROUTE_API_KEY“ ist leer), wird die Authentifizierung umgangen.---

## File Structure

src/lib/a2a/ ├── taskManager.ts # Task lifecycle (create/update/cancel/list), TTL, cleanup ├── taskExecution.ts # Generic task executor with state management ├── streaming.ts # SSE stream formatting, heartbeat, chunk/completion events ├── routingLogger.ts # Routing decision logger (stats, history, retention) └── skills/ ├── smartRouting.ts # Smart routing skill (routes via /v1/chat/completions) └── quotaManagement.ts # Quota management skill (natural-language quota queries)

src/app/a2a/ └── route.ts # Next.js API route handler (JSON-RPC 2.0 dispatch)

open-sse/mcp-server/ └── schemas/a2a.ts # Zod schemas (AgentCard, Task, JSON-RPC, SSE events)


---

## Comparison: MCP vs A2A

| Funktion | MCP-Server | A2A-Server |
| ----------------- | ------------- | ------------------------------------------------- |
|**Protokoll**| Modellkontextprotokoll | Agent-zu-Agent-Protokoll v0.3 |
|**Transport**| stdio / HTTP | HTTP (JSON-RPC 2.0) |
|**Entdeckung**| Werkzeugauflistung über MCP | `/.well-known/agent.json` |
|**Granularität**| 16 Einzelwerkzeuge | 2 Fertigkeiten auf hohem Niveau |
|**Am besten für**| IDE-Agenten (Cursor, VS-Code) | Multiagentensysteme (LangChain, CrewAI) |
|**Streaming**| Nicht unterstützt | SSE über „message/stream“ |
|**Aufgabenverfolgung**| Nein | Vollständiger Lebenszyklus (eingereicht → abgeschlossen) |
|**Beobachtbarkeit**| Audit-Protokoll pro Tool-Aufruf | Kostenrahmen + Resilienzverfolgung + Richtlinienurteil |---

## Lizenz

Teil von [OmniRoute](https://github.com/diegosouzapw/OmniRoute)  MIT-Lizenz.