# OmniRoute A2A Server Documentation (ํ•œ๊ตญ์–ด) ๐ŸŒ **Languages:** ๐Ÿ‡บ๐Ÿ‡ธ [English](../../../../frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ช๐Ÿ‡น [am](../../../am/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ธ๐Ÿ‡ฆ [ar](../../../ar/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ฆ๐Ÿ‡ฟ [az](../../../az/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ง๐Ÿ‡ฌ [bg](../../../bg/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ง๐Ÿ‡ฉ [bn](../../../bn/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ง๐Ÿ‡ฆ [bs](../../../bs/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡จ๐Ÿ‡ฟ [cs](../../../cs/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ฉ๐Ÿ‡ฐ [da](../../../da/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ฉ๐Ÿ‡ช [de](../../../de/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ฌ๐Ÿ‡ท [el](../../../el/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ช๐Ÿ‡ธ [es](../../../es/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ช๐Ÿ‡ช [et](../../../et/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ฎ๐Ÿ‡ท [fa](../../../fa/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ซ๐Ÿ‡ฎ [fi](../../../fi/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ซ๐Ÿ‡ท [fr](../../../fr/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ฎ๐Ÿ‡ช [ga](../../../ga/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ฎ๐Ÿ‡ณ [gu](../../../gu/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ณ๐Ÿ‡ฌ [ha](../../../ha/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ฎ๐Ÿ‡ฑ [he](../../../he/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ฎ๐Ÿ‡ณ [hi](../../../hi/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ญ๐Ÿ‡ท [hr](../../../hr/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ญ๐Ÿ‡บ [hu](../../../hu/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ฆ๐Ÿ‡ฒ [hy](../../../hy/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ฎ๐Ÿ‡ฉ [id](../../../id/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ณ๐Ÿ‡ฌ [ig](../../../ig/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ฎ๐Ÿ‡น [it](../../../it/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ฏ๐Ÿ‡ต [ja](../../../ja/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ฌ๐Ÿ‡ช [ka](../../../ka/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ฐ๐Ÿ‡ญ [km](../../../km/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ฎ๐Ÿ‡ณ [kn](../../../kn/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ฑ๐Ÿ‡น [lt](../../../lt/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ฑ๐Ÿ‡ป [lv](../../../lv/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ฎ๐Ÿ‡ณ [ml](../../../ml/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ฎ๐Ÿ‡ณ [mr](../../../mr/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ฒ๐Ÿ‡พ [ms](../../../ms/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ฒ๐Ÿ‡น [mt](../../../mt/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ฒ๐Ÿ‡ฒ [my](../../../my/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ณ๐Ÿ‡ต [ne](../../../ne/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ณ๐Ÿ‡ฑ [nl](../../../nl/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ณ๐Ÿ‡ด [no](../../../no/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ฎ๐Ÿ‡ณ [or](../../../or/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ฎ๐Ÿ‡ณ [pa](../../../pa/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ต๐Ÿ‡ญ [phi](../../../phi/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ต๐Ÿ‡ฑ [pl](../../../pl/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ต๐Ÿ‡น [pt](../../../pt/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ง๐Ÿ‡ท [pt-BR](../../../pt-BR/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ท๐Ÿ‡ด [ro](../../../ro/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ท๐Ÿ‡บ [ru](../../../ru/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ฑ๐Ÿ‡ฐ [si](../../../si/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ธ๐Ÿ‡ฐ [sk](../../../sk/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ธ๐Ÿ‡ฎ [sl](../../../sl/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ท๐Ÿ‡ธ [sr](../../../sr/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ธ๐Ÿ‡ช [sv](../../../sv/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ฐ๐Ÿ‡ช [sw](../../../sw/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ฎ๐Ÿ‡ณ [ta](../../../ta/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ฎ๐Ÿ‡ณ [te](../../../te/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡น๐Ÿ‡ญ [th](../../../th/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡น๐Ÿ‡ท [tr](../../../tr/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡บ๐Ÿ‡ฆ [uk-UA](../../../uk-UA/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ต๐Ÿ‡ฐ [ur](../../../ur/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡บ๐Ÿ‡ฟ [uz](../../../uz/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ป๐Ÿ‡ณ [vi](../../../vi/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡ณ๐Ÿ‡ฌ [yo](../../../yo/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡จ๐Ÿ‡ณ [zh-CN](../../../zh-CN/docs/frameworks/A2A-SERVER.md) ยท ๐Ÿ‡น๐Ÿ‡ผ [zh-TW](../../../zh-TW/docs/frameworks/A2A-SERVER.md) --- > Agent-to-Agent Protocol v0.3 โ€” ์ง€๋Šฅํ˜• ๋ผ์šฐํŒ… ์—์ด์ „ํŠธ๋กœ์„œ์˜ OmniRoute A2A ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋‘ ๊ฐ€์ง€ ํ˜•ํƒœ๋กœ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค: - `POST /a2a`์˜ **JSON-RPC 2.0**(ํ‘œ์ค€ ์ง„์ž…์ , `src/app/a2a/route.ts`์— ์ •์˜๋จ). - ๋Œ€์‹œ๋ณด๋“œ ๋ฐ ๋„๊ตฌ๋ฅผ ์œ„ํ•œ `/api/a2a/*` ํ•˜์œ„์˜ **REST**(์ƒํƒœ, ์ž‘์—… ๋ชฉ๋ก, ์ทจ์†Œ). ์ž‘์—…์€ `A2ATaskManager`(`src/lib/a2a/taskManager.ts`, ๊ธฐ๋ณธ TTL 5๋ถ„)์—์„œ ์ถ”์ ํ•ฉ๋‹ˆ๋‹ค. ์Šคํ‚ฌ์€ `src/lib/a2a/taskExecution.ts`์˜ `A2A_SKILL_HANDLERS`๋ฅผ ํ†ตํ•ด ๋””์ŠคํŒจ์น˜๋ฉ๋‹ˆ๋‹ค. ## ์—์ด์ „ํŠธ ๊ฒ€์ƒ‰ ```bash curl http://localhost:20128/.well-known/agent.json ``` OmniRoute์˜ ๊ธฐ๋Šฅ, ์Šคํ‚ฌ ๋ฐ ์ธ์ฆ ์š”๊ตฌ ์‚ฌํ•ญ์„ ์„ค๋ช…ํ•˜๋Š” ์—์ด์ „ํŠธ ์นด๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์—์ด์ „ํŠธ ์นด๋“œ์˜ `version` ํ•„๋“œ๋Š” `process.env.npm_package_version`์—์„œ ๊ฐ€์ ธ์˜ค๋ฏ€๋กœ(`src/app/.well-known/agent.json/route.ts:13` ์ฐธ์กฐ), ๋ฆด๋ฆฌ์Šคํ•  ๋•Œ๋งˆ๋‹ค `package.json`๊ณผ ์ž๋™์œผ๋กœ ๋™๊ธฐํ™”๋ฉ๋‹ˆ๋‹ค. --- ## ์ธ์ฆ ๋ชจ๋“  `/a2a` ์š”์ฒญ์—๋Š” `Authorization` ํ—ค๋”๋ฅผ ํ†ตํ•ด API ํ‚ค๋ฅผ ์ œ๊ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค: ``` Authorization: Bearer YOUR_OMNIROUTE_API_KEY ``` ์„œ๋ฒ„์— API ํ‚ค๊ฐ€ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์ง€ ์•Š์œผ๋ฉด ์ธ์ฆ์„ ๊ฑด๋„ˆ๋œ๋‹ˆ๋‹ค. ## ํ™œ์„ฑํ™” A2A๋Š” **Endpoints โ†’ A2A** ํ† ๊ธ€๋กœ ์ œ์–ด๋˜๋ฉฐ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋น„ํ™œ์„ฑํ™”๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋น„ํ™œ์„ฑํ™”๋œ ๊ฒฝ์šฐ, `GET /api/a2a/status`๋Š” `status: "disabled"` ๋ฐ `online: false`๋ฅผ ๋ณด๊ณ ํ•˜๋ฉฐ, `POST /a2a`์— ๋Œ€ํ•œ JSON-RPC ํ˜ธ์ถœ์€ JSON-RPC ์˜ค๋ฅ˜ ์ฝ”๋“œ `-32000`๊ณผ ํ•จ๊ป˜ HTTP 503์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. --- ## JSON-RPC 2.0 ๋ฉ”์„œ๋“œ ### `message/send` โ€” ๋™๊ธฐ ์‹คํ–‰ ์Šคํ‚ฌ์— ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•˜๊ณ  ์ „์ฒด ์‘๋‹ต์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค. ```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 hello world in Python"}], "metadata": {"model": "auto", "combo": "fast-coding"} } }' ``` **์‘๋‹ต:** ```json { "jsonrpc": "2.0", "id": "1", "result": { "task": { "id": "uuid", "state": "completed" }, "artifacts": [{ "type": "text", "content": "..." }], "metadata": { "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)", "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" }, "resilience_trace": [ { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." } ], "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" } } } } ``` ### `message/stream` โ€” SSE ์ŠคํŠธ๋ฆฌ๋ฐ `message/send`์™€ ๋™์ผํ•˜์ง€๋งŒ ์‹ค์‹œ๊ฐ„ ์ŠคํŠธ๋ฆฌ๋ฐ์„ ์œ„ํ•ด ์„œ๋ฒ„ ์ „์†ก ์ด๋ฒคํŠธ(Server-Sent Events)๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ```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 ์ด๋ฒคํŠธ:** ``` data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}} : heartbeat 2026-03-03T17:00:00Z data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}} ``` ### `tasks/get` โ€” ์ž‘์—… ์ƒํƒœ ์กฐํšŒ ```bash 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` โ€” ์ž‘์—… ์ทจ์†Œ ```bash 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"}}' ``` --- ## ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์Šคํ‚ฌ OmniRoute๋Š” `src/lib/a2a/taskExecution.ts::A2A_SKILL_HANDLERS`์— ์—ฐ๊ฒฐ๋œ 6๊ฐœ์˜ A2A ์Šคํ‚ฌ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๊ฐ ์Šคํ‚ฌ ๋ชจ๋“ˆ์€ `src/lib/a2a/skills/`์— ์žˆ์Šต๋‹ˆ๋‹ค. | ์Šคํ‚ฌ | ID | ์„ค๋ช… | ํƒœ๊ทธ | ์˜ˆ์‹œ | | :------------ | :------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------- | :------------------- | :---------------------------------------- | | ์Šค๋งˆํŠธ ๋ผ์šฐํŒ… | `smart-routing` | OmniRoute์˜ ์ฝค๋ณด ์—”์ง„๊ณผ ์ ์ˆ˜ ๊ณ„์‚ฐ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ตœ์ ์˜ ์ œ๊ณต์ž/์ฝค๋ณด๋กœ ๋ผ์šฐํŒ…ํ•ฉ๋‹ˆ๋‹ค | ๋ผ์šฐํŒ…, ์ œ๊ณต์ž | "์ด ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ตœ์ ์˜ ๋ชจ๋ธ๋กœ ๋ผ์šฐํŒ…ํ•ด ์ค˜" | | ํ• ๋‹น๋Ÿ‰ ๊ด€๋ฆฌ | `quota-management` | ์ œ๊ณต์ž๋ณ„ ํ• ๋‹น๋Ÿ‰ ์ƒํƒœ๋ฅผ ๋ณด๊ณ ํ•˜๊ณ  ํ˜ธ์ถœ์ž๊ฐ€ ์ œํ•œ ์ ์šฉ/์ „ํ™˜ ์‹œ์ ์„ ๊ฒฐ์ •ํ•˜๋„๋ก ์ง€์›ํ•ฉ๋‹ˆ๋‹ค | ํ• ๋‹น๋Ÿ‰, ์ œ๊ณต์ž | "anthropic์˜ ํ• ๋‹น๋Ÿ‰์„ ํ™•์ธํ•ด ์ค˜" | | ์ œ๊ณต์ž ๊ฒ€์ƒ‰ | `provider-discovery` | ์„ค์น˜๋œ ์ œ๊ณต์ž๋ฅผ ๊ธฐ๋Šฅ, ๋ฌด๋ฃŒ ํ‹ฐ์–ด ์—ฌ๋ถ€, OAuth ์ƒํƒœ์™€ ํ•จ๊ป˜ ๋‚˜์—ดํ•ฉ๋‹ˆ๋‹ค | ์ œ๊ณต์ž, ๊ฒ€์ƒ‰ | "์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ œ๊ณต์ž๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”?" | | ๋น„์šฉ ๋ถ„์„ | `cost-analysis` | ์นดํƒˆ๋กœ๊ทธ์™€ ์ตœ๊ทผ ์‚ฌ์šฉ๋Ÿ‰์„ ๋ฐ”ํƒ•์œผ๋กœ ์š”์ฒญ/๋Œ€ํ™”์˜ ๋น„์šฉ์„ ์ถ”์ •ํ•ฉ๋‹ˆ๋‹ค | ๋น„์šฉ, ์‚ฌ์šฉ๋Ÿ‰ | "์ด ๋Œ€ํ™”์˜ ๋น„์šฉ์„ ์ถ”์ •ํ•ด ์ค˜" | | ์ƒํƒœ ๋ณด๊ณ ์„œ | `health-report` | ์ œ๊ณต์ž๋ณ„ ํšŒ๋กœ ์ฐจ๋‹จ๊ธฐ, ์ฟจ๋‹ค์šด, ์ž ๊ธˆ ์ƒํƒœ๋ฅผ ์ง‘๊ณ„ํ•ฉ๋‹ˆ๋‹ค | ์ƒํƒœ, ๋ณต์›๋ ฅ | "๋ชจ๋“  ์ œ๊ณต์ž์˜ ์ƒํƒœ๋ฅผ ๋ณด์—ฌ ์ค˜" | | ๊ธฐ๋Šฅ ๋ชฉ๋ก | `list-capabilities` | ์ปจํ…์ŠคํŠธ ์ฃผ์ž…์„ ์œ„ํ•œ ์›๋ณธ SKILL.md URL๊ณผ ํ•จ๊ป˜ ์ „์ฒด 45๊ฐœ ํ•ญ๋ชฉ์˜ Agent Skills ์นดํƒˆ๋กœ๊ทธ(23๊ฐœ API + 21๊ฐœ CLI + 1๊ฐœ ๊ตฌ์„ฑ)๋ฅผ ๋งˆํฌ๋‹ค์šด ํ‘œ๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค | ์นดํƒˆ๋กœ๊ทธ, ๊ฒ€์ƒ‰, ์Šคํ‚ฌ | "๋ชจ๋“  OmniRoute ๊ธฐ๋Šฅ์„ ๋‚˜์—ดํ•ด ์ค˜" | > Agent Card๋Š” ์‹ค์‹œ๊ฐ„ 352๊ฐœ ์ œ๊ณต์ž ์นดํƒˆ๋กœ๊ทธ์™€ ์ผ์น˜ํ•˜๋„๋ก ์œ ์ง€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ œ๊ณต์ž ์ˆ˜์™€ ๋ฌด๋ฃŒ/์ธ์ฆ ๋ถˆํ•„์š” ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋Š” ๋Ÿฐํƒ€์ž„ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์—์„œ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. ### `list-capabilities` ์Šคํ‚ฌ ์ƒ์„ธ ์ •๋ณด `list-capabilities` ์Šคํ‚ฌ์€ API ํ˜ธ์ถœ์„ ๋ณด๋‚ด๊ธฐ ์ „์— OmniRoute๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์„ ํŒŒ์•…ํ•ด์•ผ ํ•˜๋Š” ์™ธ๋ถ€ ์—์ด์ „ํŠธ์— ํŠนํžˆ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด ์Šคํ‚ฌ์€ ๊ตฌ์กฐํ™”๋œ ๋งˆํฌ๋‹ค์šด ํ‘œ ์•„ํ‹ฐํŒฉํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ``` | ID | ์ด๋ฆ„ | ์นดํ…Œ๊ณ ๋ฆฌ | ์˜์—ญ | ์—”๋“œํฌ์ธํŠธ/๋ช…๋ น | ์›๋ณธ URL | | --- | --- | --- | --- | --- | --- | | omni-auth | ์ธ์ฆ ๋ฐ ์„ธ์…˜ | api | auth | POST /api/auth/login, ... | https://raw.githubusercontent.com/... | ... ``` ๊ฐ ํ–‰์—๋Š” ์—์ด์ „ํŠธ๊ฐ€ ์ „์ฒด SKILL.md๋ฅผ ์ฆ‰์‹œ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋„๋ก `rawUrl` ์—ด์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. `metadata.totalSkills` ํ•„๋“œ๋Š” ์นดํƒˆ๋กœ๊ทธ ํฌ๊ธฐ(ํ˜„์žฌ 45๊ฐœ)๋ฅผ ๋ฐ˜์˜ํ•ฉ๋‹ˆ๋‹ค. ๊ตฌํ˜„ ํŒŒ์ผ: `src/lib/a2a/skills/listCapabilities.ts`. [AGENT-SKILLS.md](./AGENT-SKILLS.md)๋„ ์ฐธ์กฐํ•˜์„ธ์š”. --- ## REST API(๋ณด์กฐ) JSON-RPC ์—”๋“œํฌ์ธํŠธ `/a2a`๋Š” ํ‘œ์ค€ A2A ์ง„์ž…์ ์ž…๋‹ˆ๋‹ค. ์•„๋ž˜ REST ์—”๋“œํฌ์ธํŠธ๋Š” ๋Œ€์‹œ๋ณด๋“œ ๋ฐ ์™ธ๋ถ€ ๋„๊ตฌ๋ฅผ ์œ„ํ•œ ๋ณด์กฐ ์•ก์„ธ์Šค๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. | ์—”๋“œํฌ์ธํŠธ | ๋ฉ”์„œ๋“œ | ์„ค๋ช… | ์ธ์ฆ | | :--------------------------- | :----- | :-------------------------------------------------------- | :----------------------------------------------- | | `/api/a2a/status` | GET | ์„œ๋ฒ„ ์ƒํƒœ, ๋“ฑ๋ก๋œ ์Šคํ‚ฌ | (๊ณต๊ฐœ) | | `/api/a2a/tasks` | GET | ํ•„ํ„ฐ๋ฅผ ์ ์šฉํ•˜์—ฌ ์ž‘์—… ๋ชฉ๋ก ์กฐํšŒ | ๊ด€๋ฆฌ | | `/api/a2a/tasks/[id]` | GET | ID๋กœ ์ž‘์—… ์กฐํšŒ | ๊ด€๋ฆฌ | | `/api/a2a/tasks/[id]/cancel` | POST | ์‹คํ–‰ ์ค‘์ธ ์ž‘์—… ์ทจ์†Œ | ๊ด€๋ฆฌ | | `/.well-known/agent.json` | GET | ์—์ด์ „ํŠธ ์นด๋“œ(A2A ๊ฒ€์ƒ‰) | (๊ณต๊ฐœ, 3600์ดˆ ๋™์•ˆ ์บ์‹œ๋จ) | | `/api/a2a/tasks` | POST | OmniConductor ํ”Œ๋ฆฟ์œผ๋กœ์˜ ์ธ๋ฐ”์šด๋“œ ์œ„์ž„(Conductor PRD RF5) | Bearer์™€ `OMNIROUTE_API_KEY` ๋น„๊ต + `a2aEnabled` | **์ธ๋ฐ”์šด๋“œ Conductor ์œ„์ž„(`POST /api/a2a/tasks`):** ์™ธ๋ถ€ A2A ์—์ด์ „ํŠธ๋Š” OmniRoute๋ฅผ ํ†ตํ•ด ์ฝ”๋”ฉ ์ž‘์—…์„ OmniConductor ํ”Œ๋ฆฟ์— ์œ„์ž„ํ•ฉ๋‹ˆ๋‹ค. ๋ณธ๋ฌธ: `{ skill: "conductor" | "conductor-cli-", messages: [{role, content}], metadata: { conductor: { repo: { url, base_ref? }, mode?, cli?, model? } } }` โ€” Conductor ํ”Œ๋ฆฟ ์Šคํ‚ฌ(์—์ด์ „ํŠธ ์นด๋“œ์— ๋ช…์‹œ๋œ ์Šคํ‚ฌ)๋งŒ ์œ„์ž„ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํ”Œ๋ฆฟ์ด git ์ €์žฅ์†Œ์—์„œ ์ž‘์—…ํ•˜๋ฏ€๋กœ `metadata.conductor.repo.url`์€ ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค. ์ด ๋ผ์šฐํŠธ๋Š” ์„œ๋ฒ„ ์ธก `CONDUCTOR_ORCHESTRATOR_TOKEN`(๋Œ€์ฒด ๊ฐ’: `CONDUCTOR_HUB_TOKEN`)์„ ์‚ฌ์šฉํ•˜์—ฌ ํ—ˆ๋ธŒ์˜ `POST /v1/tasks`๋กœ ๋ณ€ํ™˜ํ•˜๊ณ  `201 { conductor_task_id, state: "submitted" }`๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ž‘์—… ์ƒํƒœ๋Š” SSEโ†’A2A ๋ฏธ๋Ÿฌ(RF1)๋ฅผ ํ†ตํ•ด ๋‹ค์‹œ ์ „๋‹ฌ๋˜๋ฉฐ `GET /api/a2a/tasks?skill=conductor`๋ฅผ ํ†ตํ•ด ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. --- ## ์ƒˆ ์Šคํ‚ฌ ์ถ”๊ฐ€ํ•˜๊ธฐ 1. **์Šคํ‚ฌ ํŒŒ์ผ ์ƒ์„ฑ:** `src/lib/a2a/skills/.ts` `(task: A2ATask) => Promise<{ artifacts, metadata }>` ํ˜•ํƒœ์˜ ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ฅผ ๋‚ด๋ณด๋ƒ…๋‹ˆ๋‹ค. `smartRouting.ts`์™€ ๊ฐ™์€ ๊ธฐ์กด ์Šคํ‚ฌ์˜ ๊ตฌ์กฐ๋ฅผ ๋”ฐ๋ฅด์„ธ์š”. 2. **ํ•ธ๋“ค๋Ÿฌ ๋“ฑ๋ก:** `src/lib/a2a/taskExecution.ts`์˜ `A2A_SKILL_HANDLERS`์— ํ•ญ๋ชฉ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ```typescript export const A2A_SKILL_HANDLERS = { // ...๊ธฐ์กด ์Šคํ‚ฌ "your-skill": async (task) => { const skillModule = await import("./skills/yourSkill"); return skillModule.executeYourSkill(task); }, }; ``` 3. **์—์ด์ „ํŠธ ์นด๋“œ์— ๊ณต๊ฐœ:** `src/app/.well-known/agent.json/route.ts`์˜ `skills` ๋ฐฐ์—ด์— ๋‹ค์Œ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ```json { "id": "your-skill", "name": "Your Skill", "description": "Brief, intent-focused description", "tags": ["routing", "quota"], "examples": ["Sample natural-language invocation"] } ``` 4. **ํ…Œ์ŠคํŠธ ์ž‘์„ฑ:** `tests/unit/a2a-.test.ts`. ์ •์ƒ ๊ฒฝ๋กœ์™€ ์˜ค๋ฅ˜ ๊ฒฝ๋กœ๋ฅผ ๋ชจ๋‘ ๋‹ค๋ฃจ์„ธ์š”. 5. ์ด ํŒŒ์ผ์˜ `Available Skills` ํ‘œ์— ์ƒˆ ์Šคํ‚ฌ์„ **๋ฌธ์„œํ™”**ํ•˜์„ธ์š”. --- ## ์ž‘์—… TTL ์ž‘์—…์€ `ttlMinutes`(๊ธฐ๋ณธ๊ฐ’ 5๋ถ„) ํ›„ ๋งŒ๋ฃŒ๋ฉ๋‹ˆ๋‹ค. ์ด ๊ฐ’์€ `src/lib/a2a/taskManager.ts:82`์˜ `A2ATaskManager` ์ƒ์„ฑ์ž์—์„œ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค. ๊ฐ’์„ ์‚ฌ์šฉ์ž ์ง€์ •ํ•˜๋ ค๋ฉด `A2ATaskManager` ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ์„ ํฌํฌํ•˜๊ณ  ๋‹ค๋ฅธ ๊ฐ’์„ ์ „๋‹ฌํ•˜์„ธ์š”(์˜ˆ: TTL์„ 15๋ถ„์œผ๋กœ ์„ค์ •ํ•˜๋ ค๋ฉด `new A2ATaskManager(15)`). ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ธํ„ฐ๋ฒŒ์€ 60์ดˆ๋งˆ๋‹ค ๋งŒ๋ฃŒ๋œ ์ž‘์—…์„ ์ •๋ฆฌํ•ฉ๋‹ˆ๋‹ค. --- ## ์ž‘์—… ์ˆ˜๋ช… ์ฃผ๊ธฐ ``` ์ œ์ถœ๋จ โ†’ ์ž‘์—… ์ค‘ โ†’ ์™„๋ฃŒ๋จ โ†’ ์‹คํŒจํ•จ โ†’ ์ทจ์†Œ๋จ ``` - ์ž‘์—…์€ ๊ธฐ๋ณธ์ ์œผ๋กœ 5๋ถ„ ํ›„ ๋งŒ๋ฃŒ๋ฉ๋‹ˆ๋‹ค([์ž‘์—… TTL](#task-ttl) ์ฐธ์กฐ). - ์ข…๋ฃŒ ์ƒํƒœ: `completed`, `failed`, `cancelled` - ์ด๋ฒคํŠธ ๋กœ๊ทธ๋Š” ๋ชจ๋“  ์ƒํƒœ ์ „ํ™˜์„ ์ถ”์ ํ•ฉ๋‹ˆ๋‹ค. --- ## ์˜ค๋ฅ˜ ์ฝ”๋“œ | ์ฝ”๋“œ | ์˜๋ฏธ | | :----- | :--------------------------------- | | -32700 | ๊ตฌ๋ฌธ ๋ถ„์„ ์˜ค๋ฅ˜(์œ ํšจํ•˜์ง€ ์•Š์€ JSON) | | -32600 | ์œ ํšจํ•˜์ง€ ์•Š์€ ์š”์ฒญ / ์ธ์ฆ๋˜์ง€ ์•Š์Œ | | -32601 | ๋ฉ”์„œ๋“œ ๋˜๋Š” ์Šคํ‚ฌ์„ ์ฐพ์„ ์ˆ˜ ์—†์Œ | | -32602 | ์œ ํšจํ•˜์ง€ ์•Š์€ ๋งค๊ฐœ๋ณ€์ˆ˜ | | -32603 | ๋‚ด๋ถ€ ์˜ค๋ฅ˜ | | -32000 | A2A ์—”๋“œํฌ์ธํŠธ๊ฐ€ ๋น„ํ™œ์„ฑํ™”๋จ | --- ## ํ†ตํ•ฉ ์˜ˆ์ œ ### Python (requests) ```python import requests resp = requests.post("http://localhost:20128/a2a", json={ "jsonrpc": "2.0", "id": "1", "method": "message/send", "params": { "skill": "smart-routing", "messages": [{"role": "user", "content": "Hello"}] } }, headers={"Authorization": "Bearer YOUR_KEY"}) result = resp.json()["result"] print(result["artifacts"][0]["content"]) print(result["metadata"]["routing_explanation"]) ``` ### TypeScript (fetch) ```typescript const resp = await fetch("http://localhost:20128/a2a", { method: "POST", headers: { "Content-Type": "application/json", Authorization: "Bearer YOUR_KEY", }, body: JSON.stringify({ jsonrpc: "2.0", id: "1", method: "message/send", params: { skill: "smart-routing", messages: [{ role: "user", content: "Hello" }], }, }), }); const { result } = await resp.json(); console.log(result.metadata.routing_explanation); ```