Files

OmniRoute A2A Server (Bahasa Melayu)

🌐 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


Protokol Agen-ke-Ejen v0.3— Membolehkan mana-mana ejen AI menggunakan OmniRoute sebagai ejen penghalaan pintar melalui JSON-RPC 2.0.

Pelayan A2A mendedahkan OmniRoute sebagaiejen kelas pertamayang boleh ditemui oleh ejen lain, mewakilkan tugas dan bekerjasama dengan menggunakan Protokol A2A.---

Seni Bina

┌──────────────────────────────────────────────────────────────────┐
│                    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

Mula Pantas

Agent Discovery

Setiap ejen yang serasi dengan A2A mendedahkanKad Ejendi /.well-known/agent.json:```bash curl http://localhost:20128/.well-known/agent.json


**Jawapan:**```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

Hantar mesej kepada kemahiran dan terima respons lengkap.```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"} } }'


**Jawapan:**```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

Sama seperti mesej/hantar tetapi mengembalikan Acara Dihantar Pelayan untuk penstriman masa nyata.```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"}] } }'


**Acara SSE:**```
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

Laluan menggesa melalui saluran paip pintar OmniRoute dengan pemerhatian penuh.

Parameter (dalam metadata):

Parameter Taip Lalai Penerangan
model rentetan "auto" Model sasaran (cth., claude-sonnet-4, gpt-4o, auto)
kombo rentetan kombo aktif Kombo khusus untuk laluan melalui
bajet nombor tiada Kos maksimum dalam USD untuk permintaan ini
peranan rentetan tiada Pembayang peranan tugas: pengekodan, semakan, perancangan, analisis, penyahpepijat, dokumentasi

Pemulangan:

Medan Penerangan
artifak[].kandungan Teks respons LLM
metadata.routing_explanation Penjelasan yang boleh dibaca oleh manusia tentang keputusan penghalaan
metadata.cost_envelope Anggaran lwn kos sebenar dengan mata wang
metadata.resilience_trace Tatasusunan acara (primary_selected, fallback_needed, dll.)
metadata.policy_verdict Sama ada permintaan itu dibenarkan dan mengapa ### quota-management

Menjawab pertanyaan bahasa semula jadi tentang kuota pembekal.

Jenis pertanyaan (disimpulkan daripada kandungan mesej):

Corak Pertanyaan Jenis Respons
Mengandungi "kedudukan", "kuota terbanyak", "terbaik" Penyedia diberi kedudukan mengikut baki kuota
Mengandungi "percuma", "cadangkan" Menyenaraikan kombo percuma atau mencadangkan pembekal peringkat percuma
Lalai Ringkasan kuota penuh dengan amaran untuk pembekal kuota rendah ---

Task Lifecycle

submitted ──→ working ──→ completed
                       ──→ failed
              ──────────→ cancelled
Negeri Penerangan
diserahkan Tugasan dibuat, beratur untuk pelaksanaan
bekerja Pengendali kemahiran sedang melaksanakan
selesai Pelaksanaan berjaya, artifak tersedia
gagal Pelaksanaan gagal atau tugas tamat tempoh (TTL: lalai 5 min)
dibatalkan Dibatalkan oleh pelanggan melalui tugas/batal
  • Terminal menyatakan: selesai, gagal, dibatalkan (tiada peralihan selanjutnya)
  • Tugasan tamat tempoh dalam diserahkan atau berfungsi ditandakan secara automatik sebagai gagal
  • Tugasan dikumpul sampah selepas 2× TTL---

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

Ejen orkestra mewakilkan penjanaan kod kepada OmniRoute, kemudian menyerahkan output kepada ejen semakan.```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

Berbilang ejen berkongsi kuota melalui OmniRoute, menggunakan kemahiran kuota untuk menyelaraskan.```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

Ejen pemantauan menyalurkan respons dan memaparkan kemajuan dalam masa nyata.```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

Untuk tugasan yang berjalan lama, undi status tugas dan bukannya menunggu serentak.```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

Kod Malar Maksudnya
-32700 Ralat hurai (JSON tidak sah)
-32600 INVALID_REQUEST Permintaan JSON-RPC tidak sah atau
-32601 KAEDAH_TIDAK_JUMPA Kaedah atau kemahiran tidak diketahui
-32602 INVALID_PARAMS Parameter tiada atau tidak sah
-32603 ERROR_INTERNAL Pelaksanaan kemahiran gagal
-32001 TUGASAN_TIDAK_JUMPA ID tugas tidak ditemui
-32002 TUGASAN_SUDAH_SELESAI Tidak boleh mengubah suai tugasan yang telah selesai
-32003 TIDAK BOLEH Kunci API tidak sah atau tiada
-32004 BAJET_MELEBIHI Permintaan melebihi belanjawan yang dikonfigurasikan
-32005 PROVIDER_TIDAK TERSEDIA Tiada pembekal tersedia ---

Authentication

Semua permintaan /a2a memerlukan token Pembawa melalui pengepala Kebenaran:``` Authorization: Bearer YOUR_OMNIROUTE_API_KEY


Jika tiada kunci API dikonfigurasikan pada pelayan (`OMNIROUTE_API_KEY` kosong), pengesahan akan dipintas.---

## 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

| Ciri | Pelayan MCP | Pelayan A2A |
| ----------------- | ---------------------------- | ------------------------------------------------- |
|**Protokol**| Protokol Konteks Model | Protokol Agen-ke-Ejen v0.3 |
|**Pengangkutan**| stdio / HTTP | HTTP (JSON-RPC 2.0) |
|**Penemuan**| Penyenaraian alat melalui MCP | `/.well-known/agent.json` |
|**Kebutiran**| 16 alatan individu | 2 kemahiran peringkat tinggi |
|**Terbaik untuk**| Ejen IDE (Kursor, Kod VS) | Sistem berbilang ejen (LangChain, CrewAI) |
|**Penstriman**| Tidak disokong | SSE melalui `mesej/strim` |
|**Penjejakan tugas**| Tidak | Kitaran hayat penuh (diserahkan → selesai) |
|**Kebolehlihatan**| Log audit setiap panggilan alat | Sampul kos + jejak ketahanan + keputusan dasar |---

## Lesen

Sebahagian daripada [OmniRoute](https://github.com/diegosouzapw/OmniRoute) — Lesen MIT.