Files
OmniRoute/docs/i18n/vi/src/lib/a2a

OmniRoute A2A Server (Tiếng Việt)

🌐 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


Giao thức giữa tác nhân với tác nhân v0.3— Cho phép mọi tác nhân AI sử dụng OmniRoute làm tác nhân định tuyến thông minh thông qua JSON-RPC 2.0.

Máy chủ A2A hiển thị OmniRoute với tư cách lànhân viên hỗ trợ hạng nhấtmà các nhân viên khác có thể khám phá, ủy quyền nhiệm vụ và cộng tác bằng cách sử dụng Giao thức A2A.---

Kiến trúc

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

Bắt đầu nhanh

Agent Discovery

Mọi tác nhân tương thích với A2A đều hiển thịThẻ tác nhântại /.well-known/agent.json:```bash curl http://localhost:20128/.well-known/agent.json


**Phản ứng:**```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

Gửi tin nhắn đến một kỹ năng và nhận được phản hồi đầy đủ.```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"} } }'


**Phản ứng:**```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

Tương tự như message/send nhưng trả về Sự kiện do máy chủ gửi để phát trực tuyến theo thời gian thực.```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"}] } }'


**Sự kiện 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

Định tuyến các lời nhắc thông qua đường dẫn thông minh của OmniRoute với khả năng quan sát đầy đủ.

Thông số (trong siêu dữ liệu):

Tham số Loại Mặc định Mô tả
người mẫu chuỗi "tự động" Mô hình mục tiêu (ví dụ: claude-sonnet-4, gpt-4o, auto)
kết hợp chuỗi kết hợp hoạt động Combo cụ thể để định tuyến
ngân sách số không Chi phí tối đa bằng USD cho yêu cầu này
role chuỗi không Gợi ý vai trò nhiệm vụ: viết mã, đánh giá, lập kế hoạch, phân tích, gỡ lỗi, tài liệu

Trả về:

Lĩnh vực Mô tả
hiện vật[].content Văn bản phản hồi LLM
siêu dữ liệu.routing_explanation Giải thích dễ hiểu về quyết định định tuyến
siêu dữ liệu.cost_envelope Ước tính so với chi phí thực tế bằng đơn vị tiền tệ
siêu dữ liệu.khả năng phục hồi_trace Mảng sự kiện (primaryselected, fallback Need, v.v.)
siêu dữ liệu.chính sách_bản án Liệu yêu cầu có được cho phép hay không và tại sao ### quota-management

Trả lời các truy vấn bằng ngôn ngữ tự nhiên về hạn ngạch của nhà cung cấp.

Các loại truy vấn (suy ra từ nội dung tin nhắn):

Mẫu truy vấn Loại phản hồi
Chứa "xếp hạng", "hạn ngạch nhiều nhất", "tốt nhất" Nhà cung cấp được xếp hạng theo hạn ngạch còn lại
Chứa "miễn phí", "gợi ý" Liệt kê các combo miễn phí hoặc đề xuất các nhà cung cấp cấp miễn phí
Mặc định Tóm tắt hạn ngạch đầy đủ kèm theo cảnh báo dành cho nhà cung cấp hạn ngạch thấp ---

Task Lifecycle

submitted ──→ working ──→ completed
                       ──→ failed
              ──────────→ cancelled
Tiểu bang Mô tả
đã gửi Tác vụ đã được tạo, xếp hàng để thực hiện
làm việc Trình xử lý kỹ năng đang thực thi
hoàn thành Thực hiện thành công, hiện vật có sẵn
thất bại Thực thi không thành công hoặc tác vụ đã hết hạn (TTL: mặc định 5 phút)
đã hủy Đã bị khách hàng hủy qua tasks/cancel
  • Trạng thái đầu cuối: đã hoàn thành, không thành công, đã hủy (không có chuyển tiếp nào nữa)
  • Các tác vụ đã hết hạn trong đã gửi hoặc đang làm việc được tự động đánh dấu là không thành công
  • Các tác vụ được thu gom rác sau 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

Tác nhân điều phối ủy quyền việc tạo mã cho OmniRoute, sau đó chuyển kết quả đầu ra cho tác nhân đánh giá.```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

Nhiều đại lý chia sẻ hạn ngạch thông qua OmniRoute, sử dụng kỹ năng hạn ngạch để phối hợp.```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

Tác nhân giám sát truyền các phản hồi và hiển thị tiến trình trong thời gian thực.```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

Đối với các tác vụ chạy dài, hãy thăm dò trạng thái tác vụ thay vì chờ đợi đồng bộ.```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

Hằng số Ý nghĩa
-32700 Lỗi phân tích cú pháp (JSON không hợp lệ)
-32600 INVALID_REQUEST Yêu cầu JSON-RPC không hợp lệ hoặc trái phép
-32601 PHƯƠNG PHÁP_NOT_FOUND Phương pháp hoặc kỹ năng không xác định
-32602 INVALID_PARAMS Tham số bị thiếu hoặc không hợp lệ
-32603 NỘI BỘ_ERROR Thực hiện kỹ năng không thành công
-32001 TASK_NOT_FOUND Không tìm thấy ID nhiệm vụ
-32002 TASK_ALREADY_COMPLETED Không thể sửa đổi một nhiệm vụ đã hoàn thành
-32003 TRÁI PHÉP Khóa API không hợp lệ hoặc bị thiếu
-32004 BUDGET_EXCEEDED Yêu cầu vượt quá ngân sách đã định cấu hình
-32005 PROVIDER_UNAVAILABLE Không có nhà cung cấp nào ---

Authentication

Tất cả các yêu cầu /a2a đều yêu cầu mã thông báo Bearer thông qua tiêu đề Ủy quyền:``` Authorization: Bearer YOUR_OMNIROUTE_API_KEY


Nếu không có khóa API nào được định cấu hình trên máy chủ (`OMNIROUTE_API_KEY` trống), xác thực sẽ bị bỏ qua.---

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

| Tính năng | Máy chủ MCP | Máy chủ A2A |
| ----------------- | ---------------------------- | ------------------------------------------------- |
|**Giao thức**| Giao thức bối cảnh mô hình | Giao thức giữa tác nhân với tác nhân v0.3 |
|**Giao thông**| stdio / HTTP | HTTP (JSON-RPC 2.0) |
|**Khám phá**| Danh sách công cụ qua MCP | `/.well-known/agent.json` |
|**Mức độ chi tiết**| 16 công cụ riêng lẻ | 2 kỹ năng cấp cao |
|**Tốt nhất cho**| Tác nhân IDE (Con trỏ, Mã VS) | Hệ thống đa tác nhân (LangChain, CrewAI) |
|**Truyền phát**| Không được hỗ trợ | SSE qua `tin nhắn/luồng` |
|**Theo dõi nhiệm vụ**| Không | Toàn bộ vòng đời (đã gửi → đã hoàn thành) |
|**Khả năng quan sát**| Nhật ký kiểm tra mỗi cuộc gọi công cụ | Đường bao chi phí + dấu vết khả năng phục hồi + phán quyết chính sách |---

## Giấy phép

Một phần của [OmniRoute](https://github.com/diegosouzapw/OmniRoute) — Giấy phép MIT.