OmniRoute A2A Server Documentation (한국어)
모든 /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 메서드
섹션 제목: “JSON-RPC 2.0 메서드”message/send — 동기 실행
섹션 제목: “message/send — 동기 실행”스킬에 메시지를 전송하고 전체 응답이 완료될 때까지 기다립니다.
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"} } }'응답:
{ "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/stream — SSE 스트리밍”message/send와 동일하지만 실시간 스트리밍을 위해 서버 전송 이벤트(Server-Sent Events)를 반환합니다.
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 — 작업 상태 조회
섹션 제목: “tasks/get — 작업 상태 조회”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 — 작업 취소
섹션 제목: “tasks/cancel — 작업 취소”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 스킬 상세 정보”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도 참조하세요.
REST API(보조)
섹션 제목: “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-<profile>", 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를 통해 확인할 수 있습니다.
새 스킬 추가하기
섹션 제목: “새 스킬 추가하기”-
스킬 파일 생성:
src/lib/a2a/skills/<your-skill>.ts(task: A2ATask) => Promise<{ artifacts, metadata }>형태의 비동기 함수를 내보냅니다.smartRouting.ts와 같은 기존 스킬의 구조를 따르세요. -
핸들러 등록:
src/lib/a2a/taskExecution.ts의A2A_SKILL_HANDLERS에 항목을 추가합니다.export const A2A_SKILL_HANDLERS = {// ...기존 스킬"your-skill": async (task) => {const skillModule = await import("./skills/yourSkill");return skillModule.executeYourSkill(task);},}; -
에이전트 카드에 공개:
src/app/.well-known/agent.json/route.ts의skills배열에 다음을 추가합니다.{"id": "your-skill","name": "Your Skill","description": "Brief, intent-focused description","tags": ["routing", "quota"],"examples": ["Sample natural-language invocation"]} -
테스트 작성:
tests/unit/a2a-<your-skill>.test.ts. 정상 경로와 오류 경로를 모두 다루세요. -
이 파일의
Available Skills표에 새 스킬을 문서화하세요.
작업 TTL
섹션 제목: “작업 TTL”작업은 ttlMinutes(기본값 5분) 후 만료됩니다. 이 값은 src/lib/a2a/taskManager.ts:82의 A2ATaskManager 생성자에서 구성됩니다. 값을 사용자 지정하려면 A2ATaskManager 인스턴스 생성을 포크하고 다른 값을 전달하세요(예: TTL을 15분으로 설정하려면 new A2ATaskManager(15)). 백그라운드 인터벌은 60초마다 만료된 작업을 정리합니다.
작업 수명 주기
섹션 제목: “작업 수명 주기”제출됨 → 작업 중 → 완료됨 → 실패함 → 취소됨- 작업은 기본적으로 5분 후 만료됩니다(작업 TTL 참조).
- 종료 상태:
completed,failed,cancelled - 이벤트 로그는 모든 상태 전환을 추적합니다.
오류 코드
섹션 제목: “오류 코드”| 코드 | 의미 |
|---|---|
| -32700 | 구문 분석 오류(유효하지 않은 JSON) |
| -32600 | 유효하지 않은 요청 / 인증되지 않음 |
| -32601 | 메서드 또는 스킬을 찾을 수 없음 |
| -32602 | 유효하지 않은 매개변수 |
| -32603 | 내부 오류 |
| -32000 | A2A 엔드포인트가 비활성화됨 |
통합 예제
섹션 제목: “통합 예제”Python (requests)
섹션 제목: “Python (requests)”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 (fetch)”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);HagiCode
HagiCode는 구조화된 워크플로, 다중 에이전트 실행, Hero Dungeon 뷰를 갖춘 에이전트 코딩 작업 공간입니다.
더 스마트하고 빠르며 즐거운 에이전트 워크플로로 유용한 소프트웨어를 만드세요.

- Smart구조화된 워크플로는 의도를 아이디어부터 배포까지 실행 가능한 경로로 바꿉니다.
- Efficient다중 에이전트 워크플로로 조사, 구현, 검토를 병렬로 진행합니다.
- FunHero Dungeon은 긴 코딩 세션을 시각적이고 협업적인 경험으로 만듭니다.