GEODE의 도구 호출은 특정 프로바이더 payload가 아니라 AgenticLoop의 공통 계약에서 시작합니다. 도구 정의를 adapter-neutral ToolSpec으로 만들고, 선택한 adapter가 wire 형식으로 변환합니다. 모델이 반환한 호출은 다시 하나의 ToolUseBlock으로 정규화되므로 실행기와 다음 턴은 프로바이더 문법을 알 필요가 없습니다.
한 라운드의 계약
definitions.json / MCP discovery → ToolSpec(name, description, input_schema) → AdapterCallRequest(tools, tool_choice) → provider tool call → ToolUseBlock(id, name, input) → ToolCallProcessor → tool_result → assistant call + result replay → next model round
core/tools/definitions.json과 MCP discovery 결과가 이번 호출의 도구 목록을 만듭니다.AgenticLoop가 목록과tool_choice를AdapterCallRequest에 싣습니다.- adapter가 프로바이더별 tool definition과 선택 문법으로 변환합니다.
- 응답의 호출 id, 이름, 인자를
ToolUseBlock으로 정규화합니다. ToolCallProcessor가 도구를 실행하고 id가 연결된 결과를 만듭니다.- assistant의 호출과 tool result를 함께 history에 넣어 다음 모델 라운드로 보냅니다.
도구 정의
ToolSpec 필드 | 의미 | 출처 |
|---|---|---|
name | 모델이 호출하고 registry가 handler를 찾는 안정된 이름 | definitions.json 또는 MCP tool name |
description | 도구 선택에 쓰는 모델 가시 설명 | 도구 metadata |
input_schema | 호출 인자의 JSON Schema | 도구 metadata의 입력 계약 |
이 스키마는 도구 입력 계약입니다. 모델의 최종 답변 shape를 고정하는 response_schema와는 별개입니다. 레지스트리, deferred loading, toolkit 구성은 도구와 툴셋에서 설명합니다.
도구 선택 모드
| Adapter-neutral 값 | 의미 | AgenticLoop 기본 경로 |
|---|---|---|
auto | 모델이 도구 호출과 텍스트 응답 중 선택 | 일반 라운드에서 사용 |
none | 도구 호출 금지 | round 또는 time budget의 wrap-up 구간에서 강제 |
required / any | 하나 이상의 도구 호출 요구 | adapter request 계약은 번역하지만 일반 loop는 현재 생성하지 않음 |
{"type":"tool","name":"…"} | 이름으로 한 도구 강제 | adapter request 계약은 지원하지만 일반 loop의 사용자 설정 표면은 아님 |
즉, GEODE CLI에서 평소 도구 호출은 auto이고 종료 여유가 부족해지면 none으로 전환됩니다. required와 named forcing은 adapter-neutral 내부 표면이지 현재 일반 실행의 사용자 옵션이 아닙니다.
내장 adapter 배선
| 경로 | GEODE가 만드는 요청 | 선택 변환 | 결과 replay |
|---|---|---|---|
anthropic-payganthropic-oauth | Messages API tool definition | required→any, named→tool | tool_use_id가 있는 tool_result |
openai-paygcodex-oauth | Responses API의 flat function tool, parallel_tool_calls=true | any→required, named→flat function | call_id로 묶인 function_call / function_call_output |
glm-paygglm-coding-plan | Chat Completions의 nested function tool | any→required, named→nested function | tool_call_id가 있는 role=tool message |
claude-clicodex-cli | GEODE adapter 경계는 text-only이며 supports_tools=False | 전달하지 않음 | GEODE tool result replay 없음 |
이 표는 GEODE request builder의 보장입니다. 특정 모델이 모든 선택 모드나 tool schema를 받아들인다는 모델별 호환성 주장까지 포함하지 않습니다.
복수 호출과 실행
한 응답에 tool_use block이 둘 이상이면 ToolCallProcessor가 safety tier별 batch를 만듭니다. SAFE, MCP auto-approved, 사용자가 batch 승인한 EXPENSIVE 도구는 asyncio.gather로 병렬 실행합니다. WRITE와 DANGEROUS 도구는 개별 승인 뒤 순차 실행하고, 최종 result 순서는 원래 call 순서를 유지합니다. 호출이 하나면 곧바로 순차 fast path를 사용합니다. OpenAI Responses 경로는 모델 쪽 병렬 호출도 명시적으로 켜지만, Anthropic과 GLM 요청에는 GEODE 별도 parallel toggle이 없습니다.
결과 직렬화와 다음 턴
- 일반 결과는 JSON으로 직렬화하고 원래 call id를 유지합니다.
- computer-use screenshot은 텍스트 base64가 아니라 image content block으로 되돌립니다.
- 큰 결과는 token guard를 거친 뒤 필요하면 파일로 offload하고 요약과
ref_id만 context에 남깁니다. - assistant의 호출 message와 user 쪽 tool result를 연달아 history에 추가해야 다음 턴의 id pairing이 유지됩니다.
실패와 종료
| 상황 | GEODE 동작 |
|---|---|
| 모델이 tool call 없이 텍스트로 끝냄 | 자연 종료로 처리하고 최종 텍스트를 반환 |
| 같은 도구가 연속 실패 | 2회 실패를 기록한 뒤 다음 호출에서 adaptive recovery chain을 시작 |
| 전체 도구 오류가 3회 이상 연속 | 다른 접근을 요구하는 backpressure hint를 다음 턴에 삽입 |
| 서로 다른 라운드에서 같은 도구와 같은 인자를 5회 반복 | no-progress loop로 보고 diversity hint를 삽입 |
| CLI adapter를 선택 | 도구 schema를 subprocess에 전달하지 않는 text-only 경로 |
구현 기준점
core/llm/adapters/base.py:ToolSpec,AdapterCallRequest.core/llm/tool_choice.py: provider별 선택 모드 정규화.core/llm/adapters/translation.py: loop와 adapter 사이 공통 shape.core/agent/tool_executor/processor.py: 실행, 병렬화, 결과 직렬화.core/agent/loop/agent_loop.py: wrap-up 선택과 다음 라운드 replay.
다음
- 구조화 출력. 최종 답변의 JSON Schema 계약.
- 도구와 툴셋. registry, deferred loading, 접근 제어.
- 커스텀 도구 만들기. 새
ToolSpec의 원천을 추가하는 절차.