에이전트 클라이언트 프로토콜

·3분 읽기

원문: Koog Documentation — agent-client-protocol 이 글은 Koog 공식 문서의 agent-client-protocol 페이지를 한국어로 옮긴 번역본입니다. 문서 구조와 링크 의미를 유지하되, MkDocs 전용 UI 문법은 블로그에서 읽기 좋도록 정리했습니다.

에이전트 클라이언트 프로토콜

ACP(에이전트 클라이언트 프로토콜)는 오픈 소스 표준화 프로토콜입니다. 이는 클라이언트 애플리케이션이 일관된 양방향 인터페이스를 통해 AI 에이전트와 통신할 수 있게 해줍니다. Koog 에이전트에 ACP를 구현하면 IDE와 같은 ACP 호환 환경에 쉽게 통합할 수 있습니다.

자세한 내용은 에이전트 클라이언트 프로토콜 문서를 참조하세요.

Koog와의 통합

Koog 프레임워크는 ACP Kotlin SDK를 사용하여 ACP와 통합됩니다. 추가 API 확장 포함. 이 통합은 다음을 제공합니다.

  • ACP 호환 클라이언트 애플리케이션을 사용한 Koog 에이전트의 표준화된 통신
  • 도구 호출, 상담원 생각, 완료에 대한 자동 실행 업데이트
  • Koog의 다중 모드 메시지 형식과 ACP의 콘텐츠 블록 간의 원활한 메시지 변환
  • ACP 세션 이벤트에 대한 Koog 에이전트 상태의 수명주기 매핑

참고

ACP Kotlin SDK는 JVM 전용이므로, ACP 통합은 현재 JVM 플랫폼에서만 사용할 수 있습니다.

종속성 추가

ACP 지원은 기본적으로 Koog에서 사용할 수 없는 선택적인 feature입니다. Koog 에이전트에 ACP를 구현하려면, ai.koog:agents-features-acp에 대한 종속성을 추가합니다. 그 자체는 com.agentclientprotocol:acp에 종속됩니다.

예를 들어 build.gradle.kts의 경우:

1dependencies {2    implementation("ai.koog:agents-features-acp:$koogVersion")3}

Koog 에이전트에 대해 ACP 활성화

Koog 에이전트의 내부 event system를 ACP 프로토콜과 연결하려면, ai.koog.agents.features.acp.AcpAgent 기능을 설치합니다. 설치되면 수명 주기 이벤트(예: 도구 호출 또는 LLM 응답)를 수신합니다. ACP 클라이언트로 보냅니다.

1val agent = AIAgent(2    promptExecutor = simpleOpenAIExecutor(System.getenv("OPENAI_API_KEY")),3    llmModel = OpenAIModels.Chat.GPT4o4) {5    install(AcpAgent) {6        this.sessionId = sessionId7        this.protocol = protocol8        this.eventsProducer = eventsProducer9        this.setDefaultNotifications = true10    }11}

주요 구성 옵션:

  • sessionId: 현재 대화 세션을 식별하는 고유 문자열입니다.
  • protocol: 하위 수준 통신에 사용되는 com.agentclientprotocol.protocol.Protocol 인스턴스입니다.
  • eventsProducer: ACP 이벤트가 전송되는 kotlinx.coroutines.channels.ProducerScope<Event>입니다. 자세한 내용은 Event streaming을 참조하세요.
  • setDefaultNotifications: 에이전트 수명 주기 이벤트에 대한 기본 알림 처리기를 등록할지 여부입니다. 자세한 내용은 Handling agent notifications을 참조하세요.

이 에이전트는 다음 장에 설명된 대로 ACP 세션 범위 내에서 실행되어야 합니다.

ACP 지원 에이전트 구현

Koog 에이전트를 ACP 클라이언트에 연결하려면, ACP Kotlin SDK의 두 가지 핵심 인터페이스를 구현합니다.

  • AgentSupport: 에이전트의 ID, 기능 및 세션 수명주기(세션 생성 또는 로드)를 관리합니다.
  • AgentSession: 단일 대화 세션을 관리하고, prompt 실행을 처리하고, 취소를 관리합니다.

AgentSessionprompt() 메서드 내부에는 ACP 지원 Koog 에이전트를 초기화하고 실행해야 하는 곳이 있습니다. 예는 다음과 같습니다.

에이전트 세션

1class MyAgentSession(2    override val sessionId: SessionId,3    private val promptExecutor: PromptExecutor,4    private val protocol: Protocol,5    private val clock: Clock6) : AgentSession {78    private var agentJob: Deferred<Unit>? = null9    private val agentMutex = Mutex()1011    override suspend fun prompt(12        content: List<ContentBlock>,13        _meta: JsonElement?14    ): Flow<Event> = channelFlow {15        val agentConfig = AIAgentConfig(16            prompt = prompt("acp") {17                system("You are a helpful assistant.")18            }.appendPrompt(content),19            model = OpenAIModels.Chat.GPT4o,20            maxAgentIterations = 100021        )2223        // Ensure only one agent session runs at a time24        agentMutex.withLock {25            val agent = AIAgent(26                promptExecutor = promptExecutor,27                agentConfig = agentConfig28            ) {29                install(AcpAgent) {30                    this.sessionId = this@MyAgentSession.sessionId.value31                    this.protocol = this@MyAgentSession.protocol32                    this.eventsProducer = this@channelFlow33                    this.setDefaultNotifications = true34                }35            }3637            agentJob = async { agent.run("Hello. How can you help me?") }38            agentJob?.await()39        }40    }4142    private fun Prompt.appendPrompt(content: List<ContentBlock>): Prompt {43        return withMessages { messages ->44            messages + listOf(content.toKoogMessage(clock))45        }46    }4748    override suspend fun cancel() {49        agentJob?.cancel()50    }51}

에이전트 지원

1class MyAgentSupport(2    private val promptExecutor: PromptExecutor,3    private val clock: Clock,4    private val protocol: Protocol,5) : AgentSupport {67    override suspend fun initialize(clientInfo: ClientInfo): AgentInfo {8        return AgentInfo(9            protocolVersion = LATEST_PROTOCOL_VERSION,10            capabilities = AgentCapabilities(11                loadSession = false, // Set to true if you implement session persistence12                promptCapabilities = PromptCapabilities(13                    audio = false,14                    image = false,15                    embeddedContext = true16                )17            )18        )19    }2021    @OptIn(ExperimentalUuidApi::class)22    override suspend fun createSession(sessionParameters: SessionCreationParameters): AgentSession {23        val sessionId = SessionId(Uuid.random().toString())24        return MyAgentSession(sessionId, promptExecutor, protocol, clock)25    }2627    override suspend fun loadSession(sessionId: SessionId, sessionParameters: SessionCreationParameters): AgentSession {28        throw UnsupportedOperationException("Session loading not implemented")29    }30}

이벤트 스트리밍

예제의 AgentSessionchannelFlow 이벤트를 반환하는 prompt() 함수를 정의합니다. 그런 다음 eventsProducerthis@channelFlow와 함께 AcpAgent 기능을 설치합니다. 이를 통해 다양한 코루틴에서 이벤트를 보낼 수 있습니다.

실행 동기화

예제의 AgentSession은 뮤텍스를 사용하여 에이전트 인스턴스에 대한 액세스를 동기화합니다. ACP는 이전 에이전트 실행이 완료될 때까지 새 에이전트 실행을 트리거해서는 안 되기 때문입니다. 이를 위해 에이전트 생성 및 실행은 정의된 뮤텍스에 대해 withLock 범위에서 발생합니다.

또한 channelFlow 범위 내에서 에이전트를 비동기식으로 실행합니다. 에이전트가 조기에 취소되지 않도록 지연된 작업 agentJob으로 사용합니다.

ACP 클라이언트 입력 처리

ACP 클라이언트는 사용자 입력을 ContentBlock 개체 목록으로 보냅니다. Koog에서 이를 처리하려면 List<ContentBlock>.toKoogMessage() 확장 기능을 사용하세요. ACP 콘텐츠 블록을 Message.User로 변환합니다. agent's prompt에 추가하세요.

예제의 AgentSession은 ACP 세션에서 초기 에이전트 프롬프트를 확장하는 개인 기능을 정의합니다.

1private fun Prompt.appendPrompt(content: List<ContentBlock>): Prompt {2    return withMessages { messages ->3        messages + listOf(content.toKoogMessage(clock))4    }5}

참고

메시지에 타임스탬프를 찍으려면 Clock 인스턴스가 필요합니다.

자세한 내용은 Converting messages을 참조하세요.

메시지 변환 중

agents-features-acp 모듈은 확장 기능을 제공합니다. Koog의 내부 메시지 유형 간을 원활하게 변환합니다. 및 ACP content blocks.

ACP 클라이언트로부터 입력을 받을 때 다음 기능을 사용하십시오.

  • List<ContentBlock>.toKoogMessage()은 ACP 콘텐츠 블록 목록을 Message.User로 변환합니다.
  • ContentBlock.toKoogContentPart()은 단일 ACP 콘텐츠 블록을 ContentPart로 변환합니다.

다음 기능을 사용하여 Koog 메시지에서 ACP 이벤트 또는 콘텐츠 블록을 구성합니다.

  • Message.Response.toAcpEvents()Message.Response을 ACP 세션 업데이트 이벤트 목록으로 변환합니다.
  • ContentPart.toAcpContentBlock()ContentPart을 단일 ACP 콘텐츠 블록으로 변환합니다.

에이전트 알림 처리

기본적으로 setDefaultNotificationstrue으로 설정됩니다. ACP 지원 에이전트는 다음 알림을 자동으로 처리합니다.

  • 에이전트 완료

에이전트가 성공적으로 완료되면 PromptResponseEvent와 함께 StopReason.END_TURN을 보냅니다.

  • 에이전트 실행 실패

적절한 중지 이유와 함께 PromptResponseEvent을 보냅니다.

  • StopReason.MAX_TURN_REQUESTS 에이전트가 최대 반복을 초과하는 경우

  • StopReason.REFUSAL 기타 실행 실패

  • LLM 응답

LLM 응답을 ACP 이벤트(텍스트, 도구 호출, 추론)로 변환하여 보냅니다.

  • 도구 호출 수명주기

도구 호출 상태 변경을 보고합니다.

  • ToolCallStatus.IN_PROGRESS 도구 호출이 시작될 때
  • ToolCallStatus.COMPLETED 도구 호출이 성공한 경우
  • ToolCallStatus.FAILED 도구 호출이 실패한 경우

알림 처리를 사용자 정의하려면, setDefaultNotifications = false을 설정하고 사양에 따라 에이전트 이벤트를 처리합니다.

맞춤 이벤트 보내기

자동알림 외에도 에이전트 실행 중 언제든지 ACP 클라이언트에 사용자 정의 이벤트를 보낼 수 있습니다. withAcpAgent 블록 내에서 sendEvent을 사용합니다. 이는 진행률 업데이트, 사용자 정의 상태 메시지 또는 계획 업데이트에 유용합니다.

예를 들어 노드에서 AIAgentContext 내에서 이 작업을 수행할 수 있습니다.

1val plan: Plan = TODO()23val strategy = strategy<Unit, Unit>("my-strategy") {4    val node by node<Unit, Unit> {5        withAcpAgent {6            sendEvent(7                Event.SessionUpdateEvent(8                    SessionUpdate.PlanUpdate(plan.entries)9                )10            )11        }12    }13}

또한 기본 protocol에 액세스하여 인증 요청과 같은 사용자 지정 요청을 클라이언트에 보낼 수도 있습니다.

1val strategy = strategy<Unit, Unit>("my-strategy") {2    val node by node<Unit, Unit> {3        withAcpAgent {4            protocol.sendRequest(5                AcpMethod.AgentMethods.Authenticate,6                AuthenticateRequest(methodId = AuthMethodId("Google"))7            )8        }9    }10}

Koog 저장소의 /examples에서 Koog 에이전트의 작업 예제를 찾을 수 있습니다.

콘솔 기반 ACP 클라이언트 실행

이 예에서는 간단한 Koog 에이전트와 상호 작용하는 콘솔 기반 ACP 클라이언트를 실행합니다.

  1. /examples/simple-examples을 엽니다.
  2. README 참조 LLM 제공업체에 대한 API 키 구성에 대한 자세한 내용을 확인하세요.
  3. runExampleAcpApp Gradle 작업을 실행합니다.
  4. ACP 클라이언트가 콘솔에서 시작되면 다음과 같이 에이전트에 대한 요청을 입력합니다.
1List files in the current directory and create a new file named 'acp-test.txt' with the content 'Hello from ACP!'.
  1. 콘솔에서 이벤트 추적을 관찰합니다. Koog 이벤트가 ACP 이벤트로 변환되어 클라이언트로 전송되는 방법을 보여줍니다.

ACP 지원 Koog 에이전트를 JetBrains IDE에 연결

이 예에서는 ACP 지원 에이전트를 생성하고 IntelliJ IDEA에 연결하는 방법을 보여줍니다.

  1. /examples/acp-agent 열기
  2. installDist Gradle 작업을 실행합니다.
  3. 이렇게 하면 에이전트 실행 파일이 생성됩니다: build/install/acp-agent/bin/acp-agent (Windows의 경우 acp-agent.bat).
  4. IntelliJ IDEA(또는 다른 JetBrains IDE)를 엽니다.
  5. AI Chat > 옵션 > 사용자 지정 에이전트 추가로 이동합니다.
  6. 열린 acp.json 파일에 다음을 붙여넣습니다.
1{2    "agent_servers": {3        "Koog Agent": {4            "command": "/absolute/path/to/acp-agent/build/install/acp-agent/bin/acp-agent",5            "args": [],6            "env": {7                "OPENAI_API_KEY": "paste-your-api-key-here"8            }9        }10    }11}

구성 매개변수:

  • agent_servers: 하나 이상의 에이전트 구성을 포함하는 개체
  • Koog Agent: IDE의 에이전트 선택기에 표시되는 표시 이름
  • command: 에이전트 실행 파일의 절대 경로
  • args: 명령줄 인수(이 에이전트의 경우 비어 있음)
  • env: 에이전트 프로세스에 전달된 환경 변수(이 예에서는 OpenAI API 키)
  1. AI Chat 도구 창에서 에이전트를 사용할 수 있어야 합니다.

IDE에 사용자 지정 에이전트를 추가하는 방법에 대한 자세한 내용은 다음을 참조하세요. AI Assistant documentation 참조 및 this blog post.