Agent Client Protocol 아키텍처
ACP은 코딩 인터페이스와 코딩 에이전트 간의 관계를 표준화합니다. 이를 통해 두 주체는 기능을 설정하고, 프로젝트 세션을 열고, 프롬프트를 교환하고, 진행 상황을 스트리밍하고, 권한을 요청하고, 작업을 취소하고, 세션을 닫거나 재개할 수 있는 공통 방식을 갖게 됩니다.
두 가지 역할
| 역할 | 책임 |
|---|---|
| 클라이언트 / 호스트 | 에이전트 프로세스를 시작하고, 사람과의 인터페이스를 제공하며, 작업 공간을 선택하고, 선택적 파일, 터미널 및 MCP 서버를 제공하고, 권한 정책을 적용하며, 실시간 업데이트를 렌더링합니다 |
| ACP 에이전트 | 프로젝트 세션과 프롬프트를 수락하고, 코딩 작업을 수행하며, 메시지와 도구 활동을 보고하고, 필요한 경우 권한을 요청하며, 유형화된 중지 사유를 반환합니다 |
ADK-Rust은 어느 역할이든 맡을 수 있습니다. 이는 두 가지 배포 방향일 뿐, 서로 다른 두 프로토콜이 아닙니다.
ADK-Rust가 다른 코딩 에이전트를 소비할 때, 왼쪽은 ADK-Rust이고 오른쪽은 외부 프로세스입니다. 편집기가 ADK-Rust 에이전트를 소비할 때는 편집기가 왼쪽을 소유하고 AcpServer가 오른쪽을 소유합니다.
하나의 ACP 턴
연결은 양방향입니다. 프롬프트가 실행되는 동안에는 에이전트가 최종 프롬프트 응답 전에 알림이나 권한 요청을 보낼 수 있으므로, 클라이언트는 계속 읽어야 합니다.
세션 식별자와 상태
ACP 세션은 하나의 프로젝트에 대한 계속되는 대화를 식별합니다. 여기에는 절대 cwd, 선택적 추가 디렉터리, 여러 프롬프트, 스트리밍 업데이트, 그리고 생명주기가 포함됩니다. ADK-Rust 서버에서는 하나의 ACP 세션이 하나의 ADK-Rust 세션에 매핑되므로 모델 히스토리와 세션 상태가 같은 대화에 계속 연결됩니다.
활성 연결을 닫는 것은 저장된 히스토리를 삭제하는 것과 다릅니다.
session/close는 활성 세션과 그 프로세스를 해제합니다;session/resume는 저장된 ADK 세션 상태에 연결합니다;session/load는 저장된 세션을 다시 활성화하고, 저장된 대화를 순서가 보장된session/update알림으로 클라이언트에 다시 재생한 뒤 요청을 완료합니다;session/fork는 저장된 세션을 새 세션 ID로 분기하며, 저장된 히스토리는 원본의 복사본이고 원본은 그대로 유지됩니다;session/delete는 저장된 세션을 제거합니다;session/list는 구성된SessionService를 통해 보이는 세션을 반환합니다.
session/load는 제공된 cwd을 세션에 저장된 작업 디렉터리와 session/resume와 같은 방식으로 검증하고, 알 수 없는 세션 식별자에 대해서는 session-not-found 오류를 반환합니다. 재생은 저장된 각 사용자, 에이전트, 생각, 도구 이벤트를 원래의 시간 순서대로 해당 SessionUpdate 변형에 매핑하므로, 다시 연결하는 편집기는 발생한 순서대로 보이는 히스토리를 복원합니다.
대화형 세션 제어
에이전트는 SessionControls 제공자를 제공하여 클라이언트에 대화형 제어를 노출할 수 있습니다. 그렇게 하면 서버는 session/new, session/load, session/resume, session/fork 응답에서 이를 광고합니다.
- 모드 — 현재 선택 항목이 있는 이름 있는 모드 집합(예: "ask" 대 "code")입니다.
session/set_mode는 요청된 모드를 광고된 집합과 대조해 검증하고, 이를 기록하며,CurrentModeUpdate를 내보냅니다. 알 수 없는 모드는 거부되며 현재 모드는 변경되지 않습니다. - 구성 옵션 — 클라이언트가 읽고 변경할 수 있는 선택 항목과 토글입니다.
session/set_config_option는 값을 옵션의 선언된 선택지와 대조해 검증하고, 이를 기록하며,ConfigOptionUpdate를 내보냅니다. 알 수 없는 옵션이나 잘못된 값은 거부됩니다. - 사용 가능한 명령 — 세션이 활성화될 때 ACP 슬래시 명령이
AvailableCommandsUpdate로 표시됩니다.
모드와 구성 선택은 ADK 세션 상태(acp:mode, acp:config:<id>)에 유지되므로, 로드, 재개, 포크를 거쳐도 유지됩니다. 기록된 세션 제목은 활성화 시와 변경될 때마다 SessionInfoUpdate로 표시됩니다. Plan 업데이트 매핑은 존재하지만, ADK 계획 원시값이 계획 항목을 노출할 때까지는 비활성 상태로 유지됩니다. SessionControls를 제공하지 않는 에이전트는 모드도 옵션도 광고하지 않으므로, 광고된 기능이 서버가 구현한 것과 정확히 일치합니다.
콘텐츠는 하나의 매핑을 통해 경계를 넘습니다
클라이언트에서 들어오는 프롬프트와 그에게 스트리밍으로 돌아가는 업데이트는 모두 하나의 콘텐츠 모듈을 통해 전달되며, 이 모듈은 ACP ContentBlock 값을 adk_core::Part 값으로, 그리고 다시 되돌려 매핑합니다. 양방향에서 하나의 매핑을 유지하면 서버 프롬프트 파서, 서버 스트리머, 그리고 클라이언트가 각 콘텐츠 유형이 어떻게 표현되는지에 대해 모두 일치합니다.
이 매핑은 페이로드를 충실하게 보존합니다. 텍스트 블록은 문자열을 그대로 유지한 채 Part::Text에 매핑됩니다. 임베디드 리소스 블록은 Part::EmbeddedResource에 매핑되며, 소스 URI, 선택적 MIME 유형, 그리고 내용을 유지합니다. 텍스트 리소스는 양방향으로 그대로 전달되며 절대 base64로 인코딩되지 않습니다. 바이너리 리소스는 전송 시 base64로 인코딩되고 경계의 ADK 쪽에서 원시 바이트로 디코딩됩니다. 이미지와 오디오 블록은 MIME 유형과 디코딩된 바이트를 보존한 채 Part::InlineData에 매핑됩니다. 서버는 이러한 프롬프트 미디어를 광고하고 수락하며, 클라이언트는 비텍스트 ADK 콘텐츠(임베디드 리소스, 이미지, 오디오)를 버리지 않고 대응하는 ACP 블록으로 전송합니다.
스트리밍 업데이트는 텍스트보다 더 많은 것을 전달합니다
프롬프트가 실행되는 동안 서버는 유형화된 ADK 이벤트를 ACP session/update 알림으로 변환합니다. 모델 텍스트와 생각은 메시지 및 생각 청크가 되고, 임베디드 리소스 콘텐츠는 임베디드 리소스 메시지 청크가 됩니다. 이 표면을 넘어, 두 종류의 업데이트가 클라이언트에 턴에 대한 더 풍부한 보기를 제공합니다.
- 사용량 업데이트. ADK 이벤트가 사용량 메타데이터를 포함할 때, 서버는 보고된 토큰 수를 반영한
UsageUpdate를 전송하며, 런타임이 보고하면 USD 비용도 함께 전송합니다. 사용량 메타데이터가 없는 이벤트는 업데이트를 생성하지 않으며, 서버는 수치를 임의로 만들지 않습니다. - 리치 도구 호출 업데이트. 도구 호출은 도구의 선언된 동작에서 추론된 도구
kind를 가진ToolCall로 시작합니다. 이후의ToolCallUpdate는 도구 결과 콘텐츠와 도구가 영향을 주었다고 보고한 파일 위치를 담고 있으므로, 편집기는 diff와 영향을 받은 파일 목록을 렌더링할 수 있습니다. 이 업데이트는 시작된ToolCall와 동일한 식별자를 유지하여 턴 전체에서 상관관계를 보존합니다.
클라이언트 방향은 일치하는 충실도를 가집니다. ADK-Rust 애플리케이션이 External_Agent을 소비할 때, 그 스트리밍 표면(OutputChunk)은 에이전트 텍스트와 생각뿐 아니라 External_Agent의 ToolCallUpdate도 노출합니다(상태, 종류, 제목, 내용 텍스트, 영향을 받은 파일 위치를 담은 id-상관 도구 업데이트로서), 그리고 UsageUpdate도 노출합니다(사용된 토큰과 크기, 그리고 보고된 경우 비용과 통화). 에이전트 메시지 텍스트는 이전과 정확히 동일하게 표시되므로, 기존 텍스트 소비자는 영향을 받지 않습니다.
권한 요청은 도구 확인과 연결됩니다
ADK-Rust 에이전트는 도구 호출(ToolConfirmationRequest)에 대한 사람의 승인을 기다리며 한 턴을 일시 중지할 수 있습니다. 서버 측에서 그 일시 중지는 도구와 그 인수를 설명하는 네이티브 ACP session/request_permission 요청이 됩니다. 클라이언트의 결과가 턴을 재개합니다. 승인하면 allow로 매핑되고, 거부나 취소는 모두 deny로 매핑되므로, 취소된 요청은 도구를 절대 실행하지 않습니다. 각 결과는 함수 호출 식별자로 정확한 호출과 연결되며, 도구 확인 결정들을 통해 러너에 다시 전달됩니다. 중첩된 권한 요청은 생성된 프롬프트 태스크에서 발행되므로, 바깥쪽 session/prompt 응답은 여전히 정상적으로 완료됩니다.
기능은 계약입니다
초기화는 장식용 핸드셰이크가 아닙니다. 각 측은 자신이 지원하는 작업과 콘텐츠만 광고합니다. ADK-Rust는 이러한 기능을 사용해 stdio만 स्वीकार하는 에이전트에게 선택적 HTTP 또는 SSE MCP 구성을 보내지 않도록 하며, 애플리케이션이 해당 구현을 제공할 때만 파일 시스템 또는 터미널 호스트 작업을 광고합니다.
서버는 프롬프트 핸들러가 수락하는 콘텐츠 유형만 정확히 광고합니다. 임베디드 리소스 콘텐츠는 adk_core::Part::EmbeddedResource에 매핑되고 이미지 및 오디오 콘텐츠는 adk_core::Part::InlineData에 매핑되므로, embedded_context, image, audio 프롬프트 기능을 광고합니다. session/load 핸들러를 등록하므로 load_session를 광고하고, session/fork 핸들러를 등록하므로 fork 세션 기능도 광고합니다. 세션 모드와 구성 옵션은 에이전트가 SessionControls 제공자를 제공할 때만 광고되므로, 제공자가 없는 에이전트는 둘 중 어느 것도 광고하지 않습니다. 원격 전송, 모델 선택기, 실험적 프로토콜 추가 사항은 계속 광고되지 않습니다. 서버가 광고하지 않은 콘텐츠 유형을 담은 프롬프트는 부분적으로 처리되는 대신 설명적인 오류와 함께 거부됩니다. 호출자는 모든 ACP 구현이 동일한 표면을 가진다고 가정하지 말고, 협상된 기능 객체를 기준으로 설계해야 합니다.