Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/binarytape_open-aidoc.json
T
OpenCode 68a9071cf1 feat: reconcile local master with origin (exa/hot-platform hunters, leaks ledger, latest results)
Local branch had diverged from origin/master (sibling commits on the same base). Rewrote local history linearly on top of origin/master, folding in all local content: exa/hot-platform discovery hunters, leaks ledger, nightly sweep orchestrator, updated .gitignore and skill docs, plus the latest hunt output and vault state. Remote-only files (vault keys, channel scripts) were restored rather than dropped, so the resulting tree is a full union of both sides.
2026-08-07 12:53:47 +08:00

1 line
86 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"repo": "binarytape/open-aidoc", "files": {"docs/ko/koog/ktor-plugin.md": {"5508b3a594cf366b2856a33998d454a290d5e964": {"t": 1785746492.037125, "n": 6691, "h": "1ca6797758fe2afe", "c": "---\nstatus: beta\n---\n\n# Ktor 통합: Koog 플러그인\n\n--8<-- \"versioning-snippets.md:beta\"\n\nKoog는 Ktor 서버에 자연스럽게 통합되어, 양측 모두에서 관용적인(idiomatic) Kotlin API를 사용하여 서버 사이드 AI 애플리케이션을 작성할 수 있게 해줍니다.\n\nKoog 플러그인을 한 번 설치하고, `application.conf`/`YAML` 또는 코드에서 LLM 제공자(provider)를 설정한 다음 라우트(route)에서 바로 에이전트를 호출하세요. 더 이상 모듈 간에 LLM 클라이언트를 복잡하게 연결할 필요가 없습니다. 라우트에서 에이전트를 요청하기만 하면 바로 사용할 준비가 됩니다.\n\n## 개요\n\n`koog-ktor` 모듈은 서버 사이드 에이전트(agentic) 개발을 위한 관용적인 Kotlin/Ktor 통합 기능을 제공합니다.\n\n- 바로 사용 가능한 Ktor 플러그인: Application에서 `install(Koog)` 호출\n- OpenAI, Anthropic, Google, OpenRouter, DeepSeek, Ollama에 대한 최고 수준의 지원\n- YAML/CONF 및 코드를 통한 중앙 집중식 설정\n- 프롬프트, 도구, 기능을 포함한 에이전트 설정 및 라우트를 위한 간단한 확장 함수\n- 직접적인 LLM 사용 (`execute`, `executeStreaming`, `moderate`)\n- JVM 전용 MCP(Model Context Protocol) 도구 통합\n\n## 의존성 추가\n\n```kotlin\ndependencies {\n implementation(\"ai.koog:koog-ktor:$koogVersion\")\n}\n```\n\n## 빠른 시작\n\n1) 제공자 설정 (`application.yaml` 또는 `application.conf`)\n\n`koog.<provider>` 아래의 중첩된 키를 사용하세요. 플러그인이 자동으로 이를 인식합니다.\n\n```yaml\n# application.yaml (Ktor 설정)\nkoog:\n openai:\n apikey: ${OPENAI_API_KEY}\n baseUrl: https://api.openai.com\n anthropic:\n apikey: ${ANTHROPIC_API_KEY}\n baseUrl: https://api.anthropic.com\n google:\n apikey: ${GOOGLE_API_KEY}\n baseUrl: https://generativelanguage.googleapis.com\n openrouter:\n apikey: ${OPENROUTER_API_KEY}\n baseUrl: https://openrouter.ai\n deepseek:\n apikey: ${DEEPSEEK_API_KEY}\n baseUrl: https://api.deepseek.com\n # koog.ollama.* 키가 존재하면 Ollama가 활성화됩니다.\n ollama:\n enable: true\n baseUrl: http://localhost:11434\n```\n\n선택 사항: 요청된 제공자가 설정되지 않았을 때 직접 LLM 호출에서 사용할 폴백(fallback)을 설정합니다.\n\n```yaml\nkoog:\n llm:\n fallback:\n provider: openai\n # 아래의 모델 식별자 섹션을 참조하세요.\n model: openai.chat.gpt4_1\n```\n\n2) 플러그인 설치 및 라우트 정의\n\n```kotlin\nfun Application.module() {\n install(Koog) {\n // 프로그래밍 방식으로 제공자를 설정할 수도 있습니다 (아래 참조)\n }\n\n routing {\n route(\"/ai\") {\n post(\"/chat\") {\n val userInput = call.receiveText()\n // 특정 모델을 사용하여 기본 단일 실행 에이전트를 생성하고 실행합니다.\n val output = aiAgent(\n strategy = reActStrategy(),\n model = OpenAIModels.Chat.GPT4_1,\n input = userInput\n )\n call.respond(HttpStatusCode.OK, output)\n }\n }\n }\n}\n```\n\n참고\n\n- `aiAgent`는 구체적인 모델(`LLModel`)이 필요합니다. 라우트별 또는 용도별로 선택하세요.\n- 더 낮은 수준의 LLM 액세스가 필요한 경우, `llm()`(`PromptExecutor`)을 직접 사용하세요.\n\n## 라우트에서 직접 LLM 사용\n\n```kotlin\npost(\"/llm-chat\") {\n val userInput = call.receiveText()\n\n val messages = llm().execute(\n prompt(\"chat\") {\n system(\"You are a helpful assistant that clarifies questions\")\n user(userInput)\n },\n GoogleModels.Gemini2_5Pro\n )\n\n // 모든 어시스턴트 메시지를 하나의 문자열로 결합합니다.\n val text = messages.joinToString(separator = \"\n\") { it.content }\n call.respond(HttpStatusCode.OK, text)\n}\n```\n\n스트리밍(Streaming)\n\n```kotlin\nget(\"/stream\") {\n val flow = llm().executeStreaming(\n prompt(\"streaming\") { user(\"Stream this response, please\") },\n OpenRouterModels.GPT4o\n )\n\n // 예시: 버퍼링 후 하나의 청크로 전송\n val sb = StringBuilder()\n flow.collect { chunk -> sb.append(chunk) }\n call.respondText(sb.toString())\n}\n```\n\n모데레이션(Moderation)\n\n```kotlin\npost(\"/moderated-chat\") {\n val userInput = call.receiveText()\n\n val moderation = llm().moderate(\n prompt(\"moderation\") { user(userInput) },\n OpenAIModels.Moderation.Omni\n )\n\n if (moderation.isHarmful) {\n call.respond(HttpStatusCode.BadRequest, \"Harmful content detected\")\n return@post\n }\n\n val output = aiAgent(\n strategy = reActStrategy(),\n model = OpenAIModels.Chat.GPT4_1,\n input = userInput\n )\n call.respond(HttpStatusCode.OK, output)\n}\n```\n\n## 프로그래밍 방식 설정 (코드 내)\n\n모든 제공자와 에이전트 동작은 `install(Koog) {}`를 통해 설정할 수 있습니다.\n\n```kotlin\ninstall(Koog) {\n llm {\n openAI(apiKey = System.getenv(\"OPENAI_API_KEY\") ?: \"\") {\n baseUrl = \"https://api.openai.com\"\n timeouts { // 아래는 기본값입니다.\n requestTimeout = 15.minutes\n connectTimeout = 60.seconds\n socketTimeout = 15.minutes\n }\n }\n anthropic(apiKey = System.getenv(\"ANTHROPIC_API_KEY\") ?: \"\")\n google(apiKey = System.getenv(\"GOOGLE_API_KEY\") ?: \"\")\n openRouter(apiKey = System.getenv(\"OPENROUTER_API_KEY\") ?: \"\")\n deepSeek(apiKey = System.getenv(\"DEEPSEEK_API_KEY\") ?: \"\")\n ollama { baseUrl = \"http://localhost:11434\" }\n\n // 제공자가 설정되지 않았을 때 PromptExecutor에서 사용할 선택적 폴백\n fallback {\n provider = LLMProvider.OpenAI\n model = OpenAIModels.Chat.GPT4_1\n }\n }\n\n agentConfig {\n // 에이전트를 위한 재사용 가능한 기본 프롬프트 제공\n prompt(name = \"agent\") {\n system(\"You are a helpful server‑side agent\")\n }\n\n // 무한 도구 호출/루프 제한\n maxAgentIterations = 10\n\n // 에이전트가 기본적으로 사용할 수 있는 도구 등록\n registerTools {\n // tool(::yourTool) // 자세한 내용은 도구 개요를 참조하세요.\n }\n\n // 에이전트 기능 설치 (트레이싱 등)\n // install(OpenTelemetry) { /* ... */ }\n }\n}\n```\n\n## 설정 내 모델 식별자 (폴백)\n\nYAML/CONF에서 `llm.fallback`을 설정할 때 다음 식별자 형식을 사용하세요.\n\n- OpenAI: `openai.chat.gpt4_1`, `openai.reasoning.o3`, `openai.costoptimized.gpt4_1mini`, `openai.audio.gpt4oaudio`, `openai.moderation.omni`\n- Anthropic: `anthropic.fable_5`, `anthropic.sonnet_4_5`, `anthropic.opus_4`, `anthropic.haiku_4_5`\n- Google: `google.gemini2_5pro`, `google.gemini2_0flash001`\n- OpenRouter: `openrouter.gpt4o`, `openrouter.gpt4`, `openrouter.claude3sonnet`\n- DeepSeek: `deepseek.deepseek-v4-flash`, `deepseek.deepseek-v4-pro`, `deepseek.deepseek-chat`, `deepseek.deepseek-reasoner`\n- Ollama: `ollama.meta.llama3.2`, `ollama.alibaba.qwq:32b`, `ollama.groq.llama3-grok-tool-use:8b`\n\n참고\n\n- OpenAI의 경우 반드시 카테고리(`chat`, `reasoning`, `costoptimized`, `audio`, `embeddings`, `moderation`)를 포함해야 합니다.\n- Ollama의 경우 `ollama.model` 및 `ollama.<maker>.<model>` 형식을 모두 지원합니다.\n\n## MCP 도구 (JVM 전용)\n\nJVM에서는 MCP 서버의 도구를 에이전트 도구 레지스트리에 추가할 수 있습니다.\n\n```kotlin\ninstall(Koog) {\n agentConfig {\n mcp {\n // SSE를 통해 등록\n sse(\"https://your-mcp-server.com/sse\")\n\n // 또는 생성된 프로세스를 통해 등록 (stdio 전송)\n // process(Runtime.getRuntime().exec(\"your-mcp-binary ...\"))\n\n // 또는 기존 MCP 클라이언트 인스턴스에서 등록\n // client(existingMcpClient)\n }\n }\n}\n```\n## 왜 Koog + Ktor인가요?\n\n- 서버에서 에이전트를 개발하기 위한 Kotlin 우선의 타입 안전한 환경\n- 깔끔하고 테스트 가능한 라우트 코드와 중앙 집중식 설정\n- 라우트별로 적합한 모델을 사용하거나, 직접 LLM 호출 시 자동으로 폴백 적용\n- 도구(tools), 모데레이션(moderation), 스트리밍(streaming), 트레이싱(tracing) 등 프로덕션 환경에 적합한 기능 제공"}, "fac66c6f7442c17423e3420a8d143c16c28f7d70": {"t": 1785764911.144884, "n": 6691, "h": "1ca6797758fe2afe", "c": "---\nstatus: beta\n---\n\n# Ktor 통합: Koog 플러그인\n\n--8<-- \"versioning-snippets.md:beta\"\n\nKoog는 Ktor 서버에 자연스럽게 통합되어, 양측 모두에서 관용적인(idiomatic) Kotlin API를 사용하여 서버 사이드 AI 애플리케이션을 작성할 수 있게 해줍니다.\n\nKoog 플러그인을 한 번 설치하고, `application.conf`/`YAML` 또는 코드에서 LLM 제공자(provider)를 설정한 다음 라우트(route)에서 바로 에이전트를 호출하세요. 더 이상 모듈 간에 LLM 클라이언트를 복잡하게 연결할 필요가 없습니다. 라우트에서 에이전트를 요청하기만 하면 바로 사용할 준비가 됩니다.\n\n## 개요\n\n`koog-ktor` 모듈은 서버 사이드 에이전트(agentic) 개발을 위한 관용적인 Kotlin/Ktor 통합 기능을 제공합니다.\n\n- 바로 사용 가능한 Ktor 플러그인: Application에서 `install(Koog)` 호출\n- OpenAI, Anthropic, Google, OpenRouter, DeepSeek, Ollama에 대한 최고 수준의 지원\n- YAML/CONF 및 코드를 통한 중앙 집중식 설정\n- 프롬프트, 도구, 기능을 포함한 에이전트 설정 및 라우트를 위한 간단한 확장 함수\n- 직접적인 LLM 사용 (`execute`, `executeStreaming`, `moderate`)\n- JVM 전용 MCP(Model Context Protocol) 도구 통합\n\n## 의존성 추가\n\n```kotlin\ndependencies {\n implementation(\"ai.koog:koog-ktor:$koogVersion\")\n}\n```\n\n## 빠른 시작\n\n1) 제공자 설정 (`application.yaml` 또는 `application.conf`)\n\n`koog.<provider>` 아래의 중첩된 키를 사용하세요. 플러그인이 자동으로 이를 인식합니다.\n\n```yaml\n# application.yaml (Ktor 설정)\nkoog:\n openai:\n apikey: ${OPENAI_API_KEY}\n baseUrl: https://api.openai.com\n anthropic:\n apikey: ${ANTHROPIC_API_KEY}\n baseUrl: https://api.anthropic.com\n google:\n apikey: ${GOOGLE_API_KEY}\n baseUrl: https://generativelanguage.googleapis.com\n openrouter:\n apikey: ${OPENROUTER_API_KEY}\n baseUrl: https://openrouter.ai\n deepseek:\n apikey: ${DEEPSEEK_API_KEY}\n baseUrl: https://api.deepseek.com\n # koog.ollama.* 키가 존재하면 Ollama가 활성화됩니다.\n ollama:\n enable: true\n baseUrl: http://localhost:11434\n```\n\n선택 사항: 요청된 제공자가 설정되지 않았을 때 직접 LLM 호출에서 사용할 폴백(fallback)을 설정합니다.\n\n```yaml\nkoog:\n llm:\n fallback:\n provider: openai\n # 아래의 모델 식별자 섹션을 참조하세요.\n model: openai.chat.gpt4_1\n```\n\n2) 플러그인 설치 및 라우트 정의\n\n```kotlin\nfun Application.module() {\n install(Koog) {\n // 프로그래밍 방식으로 제공자를 설정할 수도 있습니다 (아래 참조)\n }\n\n routing {\n route(\"/ai\") {\n post(\"/chat\") {\n val userInput = call.receiveText()\n // 특정 모델을 사용하여 기본 단일 실행 에이전트를 생성하고 실행합니다.\n val output = aiAgent(\n strategy = reActStrategy(),\n model = OpenAIModels.Chat.GPT4_1,\n input = userInput\n )\n call.respond(HttpStatusCode.OK, output)\n }\n }\n }\n}\n```\n\n참고\n\n- `aiAgent`는 구체적인 모델(`LLModel`)이 필요합니다. 라우트별 또는 용도별로 선택하세요.\n- 더 낮은 수준의 LLM 액세스가 필요한 경우, `llm()`(`PromptExecutor`)을 직접 사용하세요.\n\n## 라우트에서 직접 LLM 사용\n\n```kotlin\npost(\"/llm-chat\") {\n val userInput = call.receiveText()\n\n val messages = llm().execute(\n prompt(\"chat\") {\n system(\"You are a helpful assistant that clarifies questions\")\n user(userInput)\n },\n GoogleModels.Gemini2_5Pro\n )\n\n // 모든 어시스턴트 메시지를 하나의 문자열로 결합합니다.\n val text = messages.joinToString(separator = \"\n\") { it.content }\n call.respond(HttpStatusCode.OK, text)\n}\n```\n\n스트리밍(Streaming)\n\n```kotlin\nget(\"/stream\") {\n val flow = llm().executeStreaming(\n prompt(\"streaming\") { user(\"Stream this response, please\") },\n OpenRouterModels.GPT4o\n )\n\n // 예시: 버퍼링 후 하나의 청크로 전송\n val sb = StringBuilder()\n flow.collect { chunk -> sb.append(chunk) }\n call.respondText(sb.toString())\n}\n```\n\n모데레이션(Moderation)\n\n```kotlin\npost(\"/moderated-chat\") {\n val userInput = call.receiveText()\n\n val moderation = llm().moderate(\n prompt(\"moderation\") { user(userInput) },\n OpenAIModels.Moderation.Omni\n )\n\n if (moderation.isHarmful) {\n call.respond(HttpStatusCode.BadRequest, \"Harmful content detected\")\n return@post\n }\n\n val output = aiAgent(\n strategy = reActStrategy(),\n model = OpenAIModels.Chat.GPT4_1,\n input = userInput\n )\n call.respond(HttpStatusCode.OK, output)\n}\n```\n\n## 프로그래밍 방식 설정 (코드 내)\n\n모든 제공자와 에이전트 동작은 `install(Koog) {}`를 통해 설정할 수 있습니다.\n\n```kotlin\ninstall(Koog) {\n llm {\n openAI(apiKey = System.getenv(\"OPENAI_API_KEY\") ?: \"\") {\n baseUrl = \"https://api.openai.com\"\n timeouts { // 아래는 기본값입니다.\n requestTimeout = 15.minutes\n connectTimeout = 60.seconds\n socketTimeout = 15.minutes\n }\n }\n anthropic(apiKey = System.getenv(\"ANTHROPIC_API_KEY\") ?: \"\")\n google(apiKey = System.getenv(\"GOOGLE_API_KEY\") ?: \"\")\n openRouter(apiKey = System.getenv(\"OPENROUTER_API_KEY\") ?: \"\")\n deepSeek(apiKey = System.getenv(\"DEEPSEEK_API_KEY\") ?: \"\")\n ollama { baseUrl = \"http://localhost:11434\" }\n\n // 제공자가 설정되지 않았을 때 PromptExecutor에서 사용할 선택적 폴백\n fallback {\n provider = LLMProvider.OpenAI\n model = OpenAIModels.Chat.GPT4_1\n }\n }\n\n agentConfig {\n // 에이전트를 위한 재사용 가능한 기본 프롬프트 제공\n prompt(name = \"agent\") {\n system(\"You are a helpful server‑side agent\")\n }\n\n // 무한 도구 호출/루프 제한\n maxAgentIterations = 10\n\n // 에이전트가 기본적으로 사용할 수 있는 도구 등록\n registerTools {\n // tool(::yourTool) // 자세한 내용은 도구 개요를 참조하세요.\n }\n\n // 에이전트 기능 설치 (트레이싱 등)\n // install(OpenTelemetry) { /* ... */ }\n }\n}\n```\n\n## 설정 내 모델 식별자 (폴백)\n\nYAML/CONF에서 `llm.fallback`을 설정할 때 다음 식별자 형식을 사용하세요.\n\n- OpenAI: `openai.chat.gpt4_1`, `openai.reasoning.o3`, `openai.costoptimized.gpt4_1mini`, `openai.audio.gpt4oaudio`, `openai.moderation.omni`\n- Anthropic: `anthropic.fable_5`, `anthropic.sonnet_4_5`, `anthropic.opus_4`, `anthropic.haiku_4_5`\n- Google: `google.gemini2_5pro`, `google.gemini2_0flash001`\n- OpenRouter: `openrouter.gpt4o`, `openrouter.gpt4`, `openrouter.claude3sonnet`\n- DeepSeek: `deepseek.deepseek-v4-flash`, `deepseek.deepseek-v4-pro`, `deepseek.deepseek-chat`, `deepseek.deepseek-reasoner`\n- Ollama: `ollama.meta.llama3.2`, `ollama.alibaba.qwq:32b`, `ollama.groq.llama3-grok-tool-use:8b`\n\n참고\n\n- OpenAI의 경우 반드시 카테고리(`chat`, `reasoning`, `costoptimized`, `audio`, `embeddings`, `moderation`)를 포함해야 합니다.\n- Ollama의 경우 `ollama.model` 및 `ollama.<maker>.<model>` 형식을 모두 지원합니다.\n\n## MCP 도구 (JVM 전용)\n\nJVM에서는 MCP 서버의 도구를 에이전트 도구 레지스트리에 추가할 수 있습니다.\n\n```kotlin\ninstall(Koog) {\n agentConfig {\n mcp {\n // SSE를 통해 등록\n sse(\"https://your-mcp-server.com/sse\")\n\n // 또는 생성된 프로세스를 통해 등록 (stdio 전송)\n // process(Runtime.getRuntime().exec(\"your-mcp-binary ...\"))\n\n // 또는 기존 MCP 클라이언트 인스턴스에서 등록\n // client(existingMcpClient)\n }\n }\n}\n```\n## 왜 Koog + Ktor인가요?\n\n- 서버에서 에이전트를 개발하기 위한 Kotlin 우선의 타입 안전한 환경\n- 깔끔하고 테스트 가능한 라우트 코드와 중앙 집중식 설정\n- 라우트별로 적합한 모델을 사용하거나, 직접 LLM 호출 시 자동으로 폴백 적용\n- 도구(tools), 모데레이션(moderation), 스트리밍(streaming), 트레이싱(tracing) 등 프로덕션 환경에 적합한 기능 제공"}, "a1df25630ddaff52f6d6609cd36b0f5d164ceb13": {"t": 1785764912.9612806, "n": 6670, "h": "f46753bd3cb8dc3e", "c": "---\nstatus: beta\n---\n\n# Ktor 통합: Koog 플러그인\n\n--8<-- \"versioning-snippets.md:beta\"\n\nKoog는 Ktor 서버에 자연스럽게 통합되어, 양측 모두에서 관용적인(idiomatic) Kotlin API를 사용하여 서버 사이드 AI 애플리케이션을 작성할 수 있게 해줍니다.\n\nKoog 플러그인을 한 번 설치하고, `application.conf`/`YAML` 또는 코드에서 LLM 제공자(provider)를 설정한 다음 라우트(route)에서 바로 에이전트를 호출하세요. 더 이상 모듈 간에 LLM 클라이언트를 복잡하게 연결할 필요가 없습니다. 라우트에서 에이전트를 요청하기만 하면 바로 사용할 준비가 됩니다.\n\n## 개요\n\n`koog-ktor` 모듈은 서버 사이드 에이전트(agentic) 개발을 위한 관용적인 Kotlin/Ktor 통합 기능을 제공합니다.\n\n- 바로 사용 가능한 Ktor 플러그인: Application에서 `install(Koog)` 호출\n- OpenAI, Anthropic, Google, OpenRouter, DeepSeek, Ollama에 대한 최고 수준의 지원\n- YAML/CONF 및 코드를 통한 중앙 집중식 설정\n- 프롬프트, 도구, 기능을 포함한 에이전트 설정 및 라우트를 위한 간단한 확장 함수\n- 직접적인 LLM 사용 (`execute`, `executeStreaming`, `moderate`)\n- JVM 전용 MCP(Model Context Protocol) 도구 통합\n\n## 의존성 추가\n\n```kotlin\ndependencies {\n implementation(\"ai.koog:koog-ktor:$koogVersion\")\n}\n```\n\n## 빠른 시작\n\n1) 제공자 설정 (`application.yaml` 또는 `application.conf`)\n\n`koog.<provider>` 아래의 중첩된 키를 사용하세요. 플러그인이 자동으로 이를 인식합니다.\n\n```yaml\n# application.yaml (Ktor 설정)\nkoog:\n openai:\n apikey: ${OPENAI_API_KEY}\n baseUrl: https://api.openai.com\n anthropic:\n apikey: ${ANTHROPIC_API_KEY}\n baseUrl: https://api.anthropic.com\n google:\n apikey: ${GOOGLE_API_KEY}\n baseUrl: https://generativelanguage.googleapis.com\n openrouter:\n apikey: ${OPENROUTER_API_KEY}\n baseUrl: https://openrouter.ai\n deepseek:\n apikey: ${DEEPSEEK_API_KEY}\n baseUrl: https://api.deepseek.com\n # koog.ollama.* 키가 존재하면 Ollama가 활성화됩니다.\n ollama:\n enable: true\n baseUrl: http://localhost:11434\n```\n\n선택 사항: 요청된 제공자가 설정되지 않았을 때 직접 LLM 호출에서 사용할 폴백(fallback)을 설정합니다.\n\n```yaml\nkoog:\n llm:\n fallback:\n provider: openai\n # 아래의 모델 식별자 섹션을 참조하세요.\n model: openai.chat.gpt4_1\n```\n\n2) 플러그인 설치 및 라우트 정의\n\n```kotlin\nfun Application.module() {\n install(Koog) {\n // 프로그래밍 방식으로 제공자를 설정할 수도 있습니다 (아래 참조)\n }\n\n routing {\n route(\"/ai\") {\n post(\"/chat\") {\n val userInput = call.receiveText()\n // 특정 모델을 사용하여 기본 단일 실행 에이전트를 생성하고 실행합니다.\n val output = aiAgent(\n strategy = reActStrategy(),\n model = OpenAIModels.Chat.GPT4_1,\n input = userInput\n )\n call.respond(HttpStatusCode.OK, output)\n }\n }\n }\n}\n```\n\n참고\n\n- `aiAgent`는 구체적인 모델(`LLModel`)이 필요합니다. 라우트별 또는 용도별로 선택하세요.\n- 더 낮은 수준의 LLM 액세스가 필요한 경우, `llm()`(`PromptExecutor`)을 직접 사용하세요.\n\n## 라우트에서 직접 LLM 사용\n\n```kotlin\npost(\"/llm-chat\") {\n val userInput = call.receiveText()\n\n val messages = llm().execute(\n prompt(\"chat\") {\n system(\"You are a helpful assistant that clarifies questions\")\n user(userInput)\n },\n GoogleModels.Gemini2_5Pro\n )\n\n // 모든 어시스턴트 메시지를 하나의 문자열로 결합합니다.\n val text = messages.joinToString(separator = \"\n\") { it.content }\n call.respond(HttpStatusCode.OK, text)\n}\n```\n\n스트리밍(Streaming)\n\n```kotlin\nget(\"/stream\") {\n val flow = llm().executeStreaming(\n prompt(\"streaming\") { user(\"Stream this response, please\") },\n OpenRouterModels.GPT4o\n )\n\n // 예시: 버퍼링 후 하나의 청크로 전송\n val sb = StringBuilder()\n flow.collect { chunk -> sb.append(chunk) }\n call.respondText(sb.toString())\n}\n```\n\n모데레이션(Moderation)\n\n```kotlin\npost(\"/moderated-chat\") {\n val userInput = call.receiveText()\n\n val moderation = llm().moderate(\n prompt(\"moderation\") { user(userInput) },\n OpenAIModels.Moderation.Omni\n )\n\n if (moderation.isHarmful) {\n call.respond(HttpStatusCode.BadRequest, \"Harmful content detected\")\n return@post\n }\n\n val output = aiAgent(\n strategy = reActStrategy(),\n model = OpenAIModels.Chat.GPT4_1,\n input = userInput\n )\n call.respond(HttpStatusCode.OK, output)\n}\n```\n\n## 프로그래밍 방식 설정 (코드 내)\n\n모든 제공자와 에이전트 동작은 `install(Koog) {}`를 통해 설정할 수 있습니다.\n\n```kotlin\ninstall(Koog) {\n llm {\n openAI(apiKey = System.getenv(\"OPENAI_API_KEY\") ?: \"\") {\n baseUrl = \"https://api.openai.com\"\n timeouts { // 아래는 기본값입니다.\n requestTimeout = 15.minutes\n connectTimeout = 60.seconds\n socketTimeout = 15.minutes\n }\n }\n anthropic(apiKey = System.getenv(\"ANTHROPIC_API_KEY\") ?: \"\")\n google(apiKey = System.getenv(\"GOOGLE_API_KEY\") ?: \"\")\n openRouter(apiKey = System.getenv(\"OPENROUTER_API_KEY\") ?: \"\")\n deepSeek(apiKey = System.getenv(\"DEEPSEEK_API_KEY\") ?: \"\")\n ollama { baseUrl = \"http://localhost:11434\" }\n\n // 제공자가 설정되지 않았을 때 PromptExecutor에서 사용할 선택적 폴백\n fallback {\n provider = LLMProvider.OpenAI\n model = OpenAIModels.Chat.GPT4_1\n }\n }\n\n agentConfig {\n // 에이전트를 위한 재사용 가능한 기본 프롬프트 제공\n prompt(name = \"agent\") {\n system(\"You are a helpful server‑side agent\")\n }\n\n // 무한 도구 호출/루프 제한\n maxAgentIterations = 10\n\n // 에이전트가 기본적으로 사용할 수 있는 도구 등록\n registerTools {\n // tool(::yourTool) // 자세한 내용은 도구 개요를 참조하세요.\n }\n\n // 에이전트 기능 설치 (트레이싱 등)\n // install(OpenTelemetry) { /* ... */ }\n }\n}\n```\n\n## 설정 내 모델 식별자 (폴백)\n\nYAML/CONF에서 `llm.fallback`을 설정할 때 다음 식별자 형식을 사용하세요.\n\n- OpenAI: `openai.chat.gpt4_1`, `openai.reasoning.o3`, `openai.costoptimized.gpt4_1mini`, `openai.audio.gpt4oaudio`, `openai.moderation.omni`\n- Anthropic: `anthropic.sonnet_4_5`, `anthropic.opus_4`, `anthropic.haiku_4_5`\n- Google: `google.gemini2_5pro`, `google.gemini2_0flash001`\n- OpenRouter: `openrouter.gpt4o`, `openrouter.gpt4`, `openrouter.claude3sonnet`\n- DeepSeek: `deepseek.deepseek-v4-flash`, `deepseek.deepseek-v4-pro`, `deepseek.deepseek-chat`, `deepseek.deepseek-reasoner`\n- Ollama: `ollama.meta.llama3.2`, `ollama.alibaba.qwq:32b`, `ollama.groq.llama3-grok-tool-use:8b`\n\n참고\n\n- OpenAI의 경우 반드시 카테고리(`chat`, `reasoning`, `costoptimized`, `audio`, `embeddings`, `moderation`)를 포함해야 합니다.\n- Ollama의 경우 `ollama.model` 및 `ollama.<maker>.<model>` 형식을 모두 지원합니다.\n\n## MCP 도구 (JVM 전용)\n\nJVM에서는 MCP 서버의 도구를 에이전트 도구 레지스트리에 추가할 수 있습니다.\n\n```kotlin\ninstall(Koog) {\n agentConfig {\n mcp {\n // SSE를 통해 등록\n sse(\"https://your-mcp-server.com/sse\")\n\n // 또는 생성된 프로세스를 통해 등록 (stdio 전송)\n // process(Runtime.getRuntime().exec(\"your-mcp-binary ...\"))\n\n // 또는 기존 MCP 클라이언트 인스턴스에서 등록\n // client(existingMcpClient)\n }\n }\n}\n```\n## 왜 Koog + Ktor인가요?\n\n- 서버에서 에이전트를 개발하기 위한 Kotlin 우선의 타입 안전한 환경\n- 깔끔하고 테스트 가능한 라우트 코드와 중앙 집중식 설정\n- 라우트별로 적합한 모델을 사용하거나, 직접 LLM 호출 시 자동으로 폴백 적용\n- 도구(tools), 모데레이션(moderation), 스트리밍(streaming), 트레이싱(tracing) 등 프로덕션 환경에 적합한 기능 제공"}, "b729cbe040f2a5acdc0425c420b5abb484cf3cb3": {"t": 1785764914.3935072, "n": 6601, "h": "b026f9f3aaee9b6a", "c": "# Ktor 통합: Koog 플러그인\n\nKoog는 Ktor 서버에 자연스럽게 통합되어, 양측 모두에서 관용적인(idiomatic) Kotlin API를 사용하여 서버 사이드 AI 애플리케이션을 작성할 수 있게 해줍니다.\n\nKoog 플러그인을 한 번 설치하고, `application.conf`/`YAML` 또는 코드에서 LLM 제공자(provider)를 설정한 다음 라우트(route)에서 바로 에이전트를 호출하세요. 더 이상 모듈 간에 LLM 클라이언트를 복잡하게 연결할 필요가 없습니다. 라우트에서 에이전트를 요청하기만 하면 바로 사용할 준비가 됩니다.\n\n## 개요\n\n`koog-ktor` 모듈은 서버 사이드 에이전트 개발을 위한 관용적인 Kotlin/Ktor 통합 기능을 제공합니다.\n\n- 바로 사용 가능한 Ktor 플러그인: Application에서 `install(Koog)` 호출\n- OpenAI, Anthropic, Google, OpenRouter, DeepSeek, Ollama에 대한 최고 수준의 지원\n- YAML/CONF 및 코드를 통한 중앙 집중식 설정\n- 프롬프트, 도구, 기능을 포함한 에이전트 설정 및 라우트를 위한 간단한 확장 함수\n- 직접적인 LLM 사용 (`execute`, `executeStreaming`, `moderate`)\n- JVM 전용 MCP(Model Context Protocol) 도구 통합\n\n## 의존성 추가\n\n```kotlin\ndependencies {\n implementation(\"ai.koog:koog-ktor:$koogVersion\")\n}\n```\n\n## 빠른 시작\n\n1) 제공자 설정 (`application.yaml` 또는 `application.conf`)\n\n`koog.<provider>` 아래의 중첩된 키를 사용하세요. 플러그인이 자동으로 이를 인식합니다.\n\n```yaml\n# application.yaml (Ktor 설정)\nkoog:\n openai:\n apikey: ${OPENAI_API_KEY}\n baseUrl: https://api.openai.com\n anthropic:\n apikey: ${ANTHROPIC_API_KEY}\n baseUrl: https://api.anthropic.com\n google:\n apikey: ${GOOGLE_API_KEY}\n baseUrl: https://generativelanguage.googleapis.com\n openrouter:\n apikey: ${OPENROUTER_API_KEY}\n baseUrl: https://openrouter.ai\n deepseek:\n apikey: ${DEEPSEEK_API_KEY}\n baseUrl: https://api.deepseek.com\n # koog.ollama.* 키가 존재하면 Ollama가 활성화됩니다.\n ollama:\n enable: true\n baseUrl: http://localhost:11434\n```\n\n선택 사항: 요청된 제공자가 설정되지 않았을 때 직접 LLM 호출에서 사용할 폴백(fallback)을 설정합니다.\n\n```yaml\nkoog:\n llm:\n fallback:\n provider: openai\n # 아래의 모델 식별자 섹션을 참조하세요.\n model: openai.chat.gpt4_1\n```\n\n2) 플러그인 설치 및 라우트 정의\n\n```kotlin\nfun Application.module() {\n install(Koog) {\n // 프로그래밍 방식으로 제공자를 설정할 수도 있습니다 (아래 참조)\n }\n\n routing {\n route(\"/ai\") {\n post(\"/chat\") {\n val userInput = call.receiveText()\n // 특정 모델을 사용하여 기본 단일 실행 에이전트를 생성하고 실행합니다.\n val output = aiAgent(\n strategy = reActStrategy(),\n model = OpenAIModels.Chat.GPT4_1,\n input = userInput\n )\n call.respond(HttpStatusCode.OK, output)\n }\n }\n }\n}\n```\n\n참고\n\n- `aiAgent`는 구체적인 모델(`LLModel`)이 필요합니다. 라우트별 또는 용도별로 선택하세요.\n- 더 낮은 수준의 LLM 액세스가 필요한 경우, `llm()`(`PromptExecutor`)을 직접 사용하세요.\n\n## 라우트에서 직접 LLM 사용\n\n```kotlin\npost(\"/llm-chat\") {\n val userInput = call.receiveText()\n\n val messages = llm().execute(\n prompt(\"chat\") {\n system(\"You are a helpful assistant that clarifies questions\")\n user(userInput)\n },\n GoogleModels.Gemini2_5Pro\n )\n\n // 모든 어시스턴트 메시지를 하나의 문자열로 결합합니다.\n val text = messages.joinToString(separator = \"\n\") { it.content }\n call.respond(HttpStatusCode.OK, text)\n}\n```\n\n스트리밍(Streaming)\n\n```kotlin\nget(\"/stream\") {\n val flow = llm().executeStreaming(\n prompt(\"streaming\") { user(\"Stream this response, please\") },\n OpenRouterModels.GPT4o\n )\n\n // 예시: 버퍼링 후 하나의 청크로 전송\n val sb = StringBuilder()\n flow.collect { chunk -> sb.append(chunk) }\n call.respondText(sb.toString())\n}\n```\n\n모데레이션(Moderation)\n\n```kotlin\npost(\"/moderated-chat\") {\n val userInput = call.receiveText()\n\n val moderation = llm().moderate(\n prompt(\"moderation\") { user(userInput) },\n OpenAIModels.Moderation.Omni\n )\n\n if (moderation.isHarmful) {\n call.respond(HttpStatusCode.BadRequest, \"Harmful content detected\")\n return@post\n }\n\n val output = aiAgent(\n strategy = reActStrategy(),\n model = OpenAIModels.Chat.GPT4_1,\n input = userInput\n )\n call.respond(HttpStatusCode.OK, output)\n}\n```\n\n## 프로그래밍 방식 설정 (코드 내)\n\n모든 제공자와 에이전트 동작은 `install(Koog) {}`를 통해 설정할 수 있습니다.\n\n```kotlin\ninstall(Koog) {\n llm {\n openAI(apiKey = System.getenv(\"OPENAI_API_KEY\") ?: \"\") {\n baseUrl = \"https://api.openai.com\"\n timeouts { // 아래는 기본값입니다.\n requestTimeout = 15.minutes\n connectTimeout = 60.seconds\n socketTimeout = 15.minutes\n }\n }\n anthropic(apiKey = System.getenv(\"ANTHROPIC_API_KEY\") ?: \"\")\n google(apiKey = System.getenv(\"GOOGLE_API_KEY\") ?: \"\")\n openRouter(apiKey = System.getenv(\"OPENROUTER_API_KEY\") ?: \"\")\n deepSeek(apiKey = System.getenv(\"DEEPSEEK_API_KEY\") ?: \"\")\n ollama { baseUrl = \"http://localhost:11434\" }\n\n // 제공자가 설정되지 않았을 때 PromptExecutor에서 사용할 선택적 폴백\n fallback {\n provider = LLMProvider.OpenAI\n model = OpenAIModels.Chat.GPT4_1\n }\n }\n\n agentConfig {\n // 에이전트를 위한 재사용 가능한 기본 프롬프트 제공\n prompt(name = \"agent\") {\n system(\"You are a helpful server‑side agent\")\n }\n\n // 무한 도구 호출/루프 제한\n maxAgentIterations = 10\n\n // 에이전트가 기본적으로 사용할 수 있는 도구 등록\n registerTools {\n // tool(::yourTool) // 자세한 내용은 도구 개요를 참조하세요.\n }\n\n // 에이전트 기능 설치 (트레이싱 등)\n // install(OpenTelemetry) { /* ... */ }\n }\n}\n```\n\n## 설정 내 모델 식별자 (폴백)\n\nYAML/CONF에서 `llm.fallback`을 설정할 때 다음 식별자 형식을 사용하세요.\n\n- OpenAI: `openai.chat.gpt4_1`, `openai.reasoning.o3`, `openai.costoptimized.gpt4_1mini`, `openai.audio.gpt4oaudio`, `openai.moderation.omni`\n- Anthropic: `anthropic.sonnet_4_5`, `anthropic.opus_4`, `anthropic.haiku_4_5`\n- Google: `google.gemini2_5pro`, `google.gemini2_0flash001`\n- OpenRouter: `openrouter.gpt4o`, `openrouter.gpt4`, `openrouter.claude3sonnet`\n- DeepSeek: `deepseek.deepseek-v4-flash`, `deepseek.deepseek-v4-pro`, `deepseek.deepseek-chat`, `deepseek.deepseek-reasoner`\n- Ollama: `ollama.meta.llama3.2`, `ollama.alibaba.qwq:32b`, `ollama.groq.llama3-grok-tool-use:8b`\n\n참고\n\n- OpenAI의 경우 반드시 카테고리(`chat`, `reasoning`, `costoptimized`, `audio`, `embeddings`, `moderation`)를 포함해야 합니다.\n- Ollama의 경우 `ollama.model` 및 `ollama.<maker>.<model>` 형식을 모두 지원합니다.\n\n## MCP 도구 (JVM 전용)\n\nJVM에서는 MCP 서버의 도구를 에이전트 도구 레지스트리에 추가할 수 있습니다.\n\n```kotlin\ninstall(Koog) {\n agentConfig {\n mcp {\n // SSE를 통해 등록\n sse(\"https://your-mcp-server.com/sse\")\n\n // 또는 생성된 프로세스를 통해 등록 (stdio 전송)\n // process(Runtime.getRuntime().exec(\"your-mcp-binary ...\"))\n\n // 또는 기존 MCP 클라이언트 인스턴스에서 등록\n // client(existingMcpClient)\n }\n }\n}\n```\n## 왜 Koog + Ktor인가요?\n\n- 서버에서 에이전트를 개발하기 위한 Kotlin 우선의 타입 안전한 환경\n- 깔끔하고 테스트 가능한 라우트 코드와 중앙 집중식 설정\n- 라우트별로 적합한 모델을 사용하거나, 직접 LLM 호출 시 자동으로 폴백 적용\n- 도구(tools), 모데레이션(moderation), 스트리밍(streaming), 트레이싱(tracing) 등 프로덕션 환경에 적합한 기능 제공"}, "fc1ef79e9ff7f07c56ff7e768b27b70ad4ca9311": {"t": 1785764916.0163865, "n": 6601, "h": "9e7fca7f99407e59", "c": "# Ktor 통합: Koog 플러그인\n\nKoog는 Ktor 서버에 자연스럽게 통합되어, 양측 모두에서 관용적인(idiomatic) Kotlin API를 사용하여 서버 사이드 AI 애플리케이션을 작성할 수 있게 해줍니다.\n\nKoog 플러그인을 한 번 설치하고, `application.conf`/`YAML` 또는 코드에서 LLM 제공자(provider)를 설정한 다음 라우트(route)에서 바로 에이전트를 호출하세요. 더 이상 모듈 간에 LLM 클라이언트를 복잡하게 연결할 필요가 없습니다. 라우트에서 에이전트를 요청하기만 하면 바로 사용할 준비가 됩니다.\n\n## 개요\n\n`koog-ktor` 모듈은 서버 사이드 에이전트 개발을 위한 관용적인 Kotlin/Ktor 통합 기능을 제공합니다.\n\n- 바로 사용 가능한 Ktor 플러그인: Application에서 `install(Koog)` 호출\n- OpenAI, Anthropic, Google, OpenRouter, DeepSeek, Ollama에 대한 최고 수준의 지원\n- YAML/CONF 및 코드를 통한 중앙 집중식 설정\n- 프롬프트, 도구, 기능을 포함한 에이전트 설정 및 라우트를 위한 간단한 확장 함수\n- 직접적인 LLM 사용 (`execute`, `executeStreaming`, `moderate`)\n- JVM 전용 MCP(Model Context Protocol) 도구 통합\n\n## 의존성 추가\n\n```kotlin\ndependencies {\n implementation(\"ai.koog:koog-ktor:$koogVersion\")\n}\n```\n\n## 빠른 시작\n\n1) 제공자 설정 (`application.yaml` 또는 `application.conf`)\n\n`koog.<provider>` 아래의 중첩된 키를 사용하세요. 플러그인이 자동으로 이를 인식합니다.\n\n```yaml\n# application.yaml (Ktor 설정)\nkoog:\n openai:\n apikey: ${OPENAI_API_KEY}\n baseUrl: https://api.openai.com\n anthropic:\n apikey: ${ANTHROPIC_API_KEY}\n baseUrl: https://api.anthropic.com\n google:\n apikey: ${GOOGLE_API_KEY}\n baseUrl: https://generativelanguage.googleapis.com\n openrouter:\n apikey: ${OPENROUTER_API_KEY}\n baseUrl: https://openrouter.ai\n deepseek:\n apikey: ${DEEPSEEK_API_KEY}\n baseUrl: https://api.deepseek.com\n # koog.ollama.* 키가 존재하면 Ollama가 활성화됩니다.\n ollama:\n enable: true\n baseUrl: http://localhost:11434\n```\n\n선택 사항: 요청된 제공자가 설정되지 않았을 때 직접 LLM 호출에서 사용할 폴백(fallback)을 설정합니다.\n\n```yaml\nkoog:\n llm:\n fallback:\n provider: openai\n # 아래의 모델 식별자 섹션을 참조하세요.\n model: openai.chat.gpt4_1\n```\n\n2) 플러그인 설치 및 라우트 정의\n\n```kotlin\nfun Application.module() {\n install(Koog) {\n // 프로그래밍 방식으로 제공자를 설정할 수도 있습니다 (아래 참조)\n }\n\n routing {\n route(\"/ai\") {\n post(\"/chat\") {\n val userInput = call.receiveText()\n // 특정 모델을 사용하여 기본 단일 실행 에이전트를 생성하고 실행합니다.\n val output = aiAgent(\n strategy = reActStrategy(),\n model = OpenAIModels.Chat.GPT4_1,\n input = userInput\n )\n call.respond(HttpStatusCode.OK, output)\n }\n }\n }\n}\n```\n\n참고\n\n- `aiAgent`는 구체적인 모델(`LLModel`)이 필요합니다. 라우트별 또는 용도별로 선택하세요.\n- 더 낮은 수준의 LLM 액세스가 필요한 경우, `llm()`(`PromptExecutor`)을 직접 사용하세요.\n\n## 라우트에서 직접 LLM 사용\n\n```kotlin\npost(\"/llm-chat\") {\n val userInput = call.receiveText()\n\n val messages = llm().execute(\n prompt(\"chat\") {\n system(\"You are a helpful assistant that clarifies questions\")\n user(userInput)\n },\n GoogleModels.Gemini2_5Pro\n )\n\n // 모든 어시스턴트 메시지를 하나의 문자열로 결합합니다.\n val text = messages.joinToString(separator = \"\") { it.content }\n call.respond(HttpStatusCode.OK, text)\n}\n```\n\n스트리밍(Streaming)\n\n```kotlin\nget(\"/stream\") {\n val flow = llm().executeStreaming(\n prompt(\"streaming\") { user(\"Stream this response, please\") },\n OpenRouterModels.GPT4o\n )\n\n // 예시: 버퍼링 후 하나의 청크로 전송\n val sb = StringBuilder()\n flow.collect { chunk -> sb.append(chunk) }\n call.respondText(sb.toString())\n}\n```\n\n모데레이션(Moderation)\n\n```kotlin\npost(\"/moderated-chat\") {\n val userInput = call.receiveText()\n\n val moderation = llm().moderate(\n prompt(\"moderation\") { user(userInput) },\n OpenAIModels.Moderation.Omni\n )\n\n if (moderation.isHarmful) {\n call.respond(HttpStatusCode.BadRequest, \"Harmful content detected\")\n return@post\n }\n\n val output = aiAgent(\n strategy = reActStrategy(),\n model = OpenAIModels.Chat.GPT4_1,\n input = userInput\n )\n call.respond(HttpStatusCode.OK, output)\n}\n```\n\n## 프로그래밍 방식 설정 (코드 내)\n\n모든 제공자와 에이전트 동작은 `install(Koog) {}`를 통해 설정할 수 있습니다.\n\n```kotlin\ninstall(Koog) {\n llm {\n openAI(apiKey = System.getenv(\"OPENAI_API_KEY\") ?: \"\") {\n baseUrl = \"https://api.openai.com\"\n timeouts { // 아래는 기본값입니다.\n requestTimeout = 15.minutes\n connectTimeout = 60.seconds\n socketTimeout = 15.minutes\n }\n }\n anthropic(apiKey = System.getenv(\"ANTHROPIC_API_KEY\") ?: \"\")\n google(apiKey = System.getenv(\"GOOGLE_API_KEY\") ?: \"\")\n openRouter(apiKey = System.getenv(\"OPENROUTER_API_KEY\") ?: \"\")\n deepSeek(apiKey = System.getenv(\"DEEPSEEK_API_KEY\") ?: \"\")\n ollama { baseUrl = \"http://localhost:11434\" }\n\n // 제공자가 설정되지 않았을 때 PromptExecutor에서 사용할 선택적 폴백\n fallback {\n provider = LLMProvider.OpenAI\n model = OpenAIModels.Chat.GPT4_1\n }\n }\n\n agentConfig {\n // 에이전트를 위한 재사용 가능한 기본 프롬프트 제공\n prompt(name = \"agent\") {\n system(\"You are a helpful server‑side agent\")\n }\n\n // 무한 도구 호출/루프 제한\n maxAgentIterations = 10\n\n // 에이전트가 기본적으로 사용할 수 있는 도구 등록\n registerTools {\n // tool(::yourTool) // 자세한 내용은 도구 개요를 참조하세요.\n }\n\n // 에이전트 기능 설치 (트레이싱 등)\n // install(OpenTelemetry) { /* ... */ }\n }\n}\n```\n\n## 설정 내 모델 식별자 (폴백)\n\nYAML/CONF에서 `llm.fallback`을 설정할 때 다음 식별자 형식을 사용하세요.\n\n- OpenAI: `openai.chat.gpt4_1`, `openai.reasoning.o3`, `openai.costoptimized.gpt4_1mini`, `openai.audio.gpt4oaudio`, `openai.moderation.omni`\n- Anthropic: `anthropic.sonnet_4_5`, `anthropic.opus_4`, `anthropic.haiku_4_5`\n- Google: `google.gemini2_5pro`, `google.gemini2_0flash001`\n- OpenRouter: `openrouter.gpt4o`, `openrouter.gpt4`, `openrouter.claude3sonnet`\n- DeepSeek: `deepseek.deepseek-v4-flash`, `deepseek.deepseek-v4-pro`, `deepseek.deepseek-chat`, `deepseek.deepseek-reasoner`\n- Ollama: `ollama.meta.llama3.2`, `ollama.alibaba.qwq:32b`, `ollama.groq.llama3-grok-tool-use:8b`\n\n참고\n\n- OpenAI의 경우 반드시 카테고리(`chat`, `reasoning`, `costoptimized`, `audio`, `embeddings`, `moderation`)를 포함해야 합니다.\n- Ollama의 경우 `ollama.model` 및 `ollama.<maker>.<model>` 형식을 모두 지원합니다.\n\n## MCP 도구 (JVM 전용)\n\nJVM에서는 MCP 서버의 도구를 에이전트 도구 레지스트리에 추가할 수 있습니다.\n\n```kotlin\ninstall(Koog) {\n agentConfig {\n mcp {\n // SSE를 통해 등록\n sse(\"https://your-mcp-server.com/sse\")\n\n // 또는 생성된 프로세스를 통해 등록 (stdio 전송)\n // process(Runtime.getRuntime().exec(\"your-mcp-binary ...\"))\n\n // 또는 기존 MCP 클라이언트 인스턴스에서 등록\n // client(existingMcpClient)\n }\n }\n}\n```\n\n## 왜 Koog + Ktor인가요?\n\n- 서버에서 에이전트를 개발하기 위한 Kotlin 우선의 타입 안전한 환경\n- 깔끔하고 테스트 가능한 라우트 코드와 중앙 집중식 설정\n- 라우트별로 적합한 모델을 사용하거나, 직접 LLM 호출 시 자동으로 폴백 적용\n- 도구(tools), 모데레이션(moderation), 스트리밍(streaming), 트레이싱(tracing) 등 프로덕션 환경에 적합한 기능 제공"}, "629390827d1bd1be42720a368a357bd13df4fe1f": {"t": 1785764917.4756668, "n": 6543, "h": "48ed4c0fa322e5d4", "c": "# Ktor 통합: Koog 플러그인\n\nKoog는 Ktor 서버에 자연스럽게 통합되어, 양측 모두에서 관용적인(idiomatic) Kotlin API를 사용하여 서버 사이드 AI 애플리케이션을 작성할 수 있게 해줍니다.\n\nKoog 플러그인을 한 번 설치하고, `application.conf`/`YAML` 또는 코드에서 LLM 제공자(provider)를 설정한 다음 라우트(route)에서 바로 에이전트를 호출하세요. 더 이상 모듈 간에 LLM 클라이언트를 복잡하게 연결할 필요가 없습니다. 라우트에서 에이전트를 요청하기만 하면 바로 사용할 준비가 됩니다.\n\n## 개요\n\n`koog-ktor` 모듈은 서버 사이드 에이전트 개발을 위한 관용적인 Kotlin/Ktor 통합 기능을 제공합니다.\n\n- 바로 사용 가능한 Ktor 플러그인: Application에서 `install(Koog)` 호출\n- OpenAI, Anthropic, Google, OpenRouter, DeepSeek, Ollama에 대한 최고 수준의 지원\n- YAML/CONF 및 코드를 통한 중앙 집중식 설정\n- 프롬프트, 도구, 기능을 포함한 에이전트 설정 및 라우트를 위한 간단한 확장 함수\n- 직접적인 LLM 사용 (`execute`, `executeStreaming`, `moderate`)\n- JVM 전용 MCP(Model Context Protocol) 도구 통합\n\n## 의존성 추가\n\n```kotlin\ndependencies {\n implementation(\"ai.koog:koog-ktor:$koogVersion\")\n}\n```\n\n## 빠른 시작\n\n1) 제공자 설정 (`application.yaml` 또는 `application.conf`)\n\n`koog.<provider>` 아래의 중첩된 키를 사용하세요. 플러그인이 자동으로 이를 인식합니다.\n\n```yaml\n# application.yaml (Ktor 설정)\nkoog:\n openai:\n apikey: ${OPENAI_API_KEY}\n baseUrl: https://api.openai.com\n anthropic:\n apikey: ${ANTHROPIC_API_KEY}\n baseUrl: https://api.anthropic.com\n google:\n apikey: ${GOOGLE_API_KEY}\n baseUrl: https://generativelanguage.googleapis.com\n openrouter:\n apikey: ${OPENROUTER_API_KEY}\n baseUrl: https://openrouter.ai\n deepseek:\n apikey: ${DEEPSEEK_API_KEY}\n baseUrl: https://api.deepseek.com\n # koog.ollama.* 키가 존재하면 Ollama가 활성화됩니다.\n ollama:\n enable: true\n baseUrl: http://localhost:11434\n```\n\n선택 사항: 요청된 제공자가 설정되지 않았을 때 직접 LLM 호출에서 사용할 폴백(fallback)을 설정합니다.\n\n```yaml\nkoog:\n llm:\n fallback:\n provider: openai\n # 아래의 모델 식별자 섹션을 참조하세요.\n model: openai.chat.gpt4_1\n```\n\n2) 플러그인 설치 및 라우트 정의\n\n```kotlin\nfun Application.module() {\n install(Koog) {\n // 프로그래밍 방식으로 제공자를 설정할 수도 있습니다 (아래 참조)\n }\n\n routing {\n route(\"/ai\") {\n post(\"/chat\") {\n val userInput = call.receiveText()\n // 특정 모델을 사용하여 기본 단일 실행 에이전트를 생성하고 실행합니다.\n val output = aiAgent(\n strategy = reActStrategy(),\n model = OpenAIModels.Chat.GPT4_1,\n input = userInput\n )\n call.respond(HttpStatusCode.OK, output)\n }\n }\n }\n}\n```\n\n참고\n\n- `aiAgent`는 구체적인 모델(`LLModel`)이 필요합니다. 라우트별 또는 용도별로 선택하세요.\n- 더 낮은 수준의 LLM 액세스가 필요한 경우, `llm()`(`PromptExecutor`)을 직접 사용하세요.\n\n## 라우트에서 직접 LLM 사용\n\n```kotlin\npost(\"/llm-chat\") {\n val userInput = call.receiveText()\n\n val messages = llm().execute(\n prompt(\"chat\") {\n system(\"You are a helpful assistant that clarifies questions\")\n user(userInput)\n },\n GoogleModels.Gemini2_5Pro\n )\n\n // 모든 어시스턴트 메시지를 하나의 문자열로 결합합니다.\n val text = messages.joinToString(separator = \"\") { it.content }\n call.respond(HttpStatusCode.OK, text)\n}\n```\n\n스트리밍(Streaming)\n\n```kotlin\nget(\"/stream\") {\n val flow = llm().executeStreaming(\n prompt(\"streaming\") { user(\"Stream this response, please\") },\n OpenRouterModels.GPT4o\n )\n\n // 예시: 버퍼링 후 하나의 청크로 전송\n val sb = StringBuilder()\n flow.collect { chunk -> sb.append(chunk) }\n call.respondText(sb.toString())\n}\n```\n\n모데레이션(Moderation)\n\n```kotlin\npost(\"/moderated-chat\") {\n val userInput = call.receiveText()\n\n val moderation = llm().moderate(\n prompt(\"moderation\") { user(userInput) },\n OpenAIModels.Moderation.Omni\n )\n\n if (moderation.isHarmful) {\n call.respond(HttpStatusCode.BadRequest, \"Harmful content detected\")\n return@post\n }\n\n val output = aiAgent(\n strategy = reActStrategy(),\n model = OpenAIModels.Chat.GPT4_1,\n input = userInput\n )\n call.respond(HttpStatusCode.OK, output)\n}\n```\n\n## 프로그래밍 방식 설정 (코드 내)\n\n모든 제공자와 에이전트 동작은 `install(Koog) {}`를 통해 설정할 수 있습니다.\n\n```kotlin\ninstall(Koog) {\n llm {\n openAI(apiKey = System.getenv(\"OPENAI_API_KEY\") ?: \"\") {\n baseUrl = \"https://api.openai.com\"\n timeouts { // 아래는 기본값입니다.\n requestTimeout = 15.minutes\n connectTimeout = 60.seconds\n socketTimeout = 15.minutes\n }\n }\n anthropic(apiKey = System.getenv(\"ANTHROPIC_API_KEY\") ?: \"\")\n google(apiKey = System.getenv(\"GOOGLE_API_KEY\") ?: \"\")\n openRouter(apiKey = System.getenv(\"OPENROUTER_API_KEY\") ?: \"\")\n deepSeek(apiKey = System.getenv(\"DEEPSEEK_API_KEY\") ?: \"\")\n ollama { baseUrl = \"http://localhost:11434\" }\n\n // 제공자가 설정되지 않았을 때 PromptExecutor에서 사용할 선택적 폴백\n fallback {\n provider = LLMProvider.OpenAI\n model = OpenAIModels.Chat.GPT4_1\n }\n }\n\n agentConfig {\n // 에이전트를 위한 재사용 가능한 기본 프롬프트 제공\n prompt(name = \"agent\") {\n system(\"You are a helpful server‑side agent\")\n }\n\n // 무한 도구 호출/루프 제한\n maxAgentIterations = 10\n\n // 에이전트가 기본적으로 사용할 수 있는 도구 등록\n registerTools {\n // tool(::yourTool) // 자세한 내용은 도구 개요를 참조하세요.\n }\n\n // 에이전트 기능 설치 (트레이싱 등)\n // install(OpenTelemetry) { /* ... */ }\n }\n}\n```\n\n## 설정 내 모델 식별자 (폴백)\n\nYAML/CONF에서 `llm.fallback`을 설정할 때 다음 식별자 형식을 사용하세요.\n\n- OpenAI: `openai.chat.gpt4_1`, `openai.reasoning.o3`, `openai.costoptimized.gpt4_1mini`, `openai.audio.gpt4oaudio`, `openai.moderation.omni`\n- Anthropic: `anthropic.sonnet_4_5`, `anthropic.opus_4`, `anthropic.haiku_4_5`\n- Google: `google.gemini2_5pro`, `google.gemini2_0flash001`\n- OpenRouter: `openrouter.gpt4o`, `openrouter.gpt4`, `openrouter.claude3sonnet`\n- DeepSeek: `deepseek.deepseek-chat`, `deepseek.deepseek-reasoner`\n- Ollama: `ollama.meta.llama3.2`, `ollama.alibaba.qwq:32b`, `ollama.groq.llama3-grok-tool-use:8b`\n\n참고\n\n- OpenAI의 경우 반드시 카테고리(`chat`, `reasoning`, `costoptimized`, `audio`, `embeddings`, `moderation`)를 포함해야 합니다.\n- Ollama의 경우 `ollama.model` 및 `ollama.<maker>.<model>` 형식을 모두 지원합니다.\n\n## MCP 도구 (JVM 전용)\n\nJVM에서는 MCP 서버의 도구를 에이전트 도구 레지스트리에 추가할 수 있습니다.\n\n```kotlin\ninstall(Koog) {\n agentConfig {\n mcp {\n // SSE를 통해 등록\n sse(\"https://your-mcp-server.com/sse\")\n\n // 또는 생성된 프로세스를 통해 등록 (stdio 전송)\n // process(Runtime.getRuntime().exec(\"your-mcp-binary ...\"))\n\n // 또는 기존 MCP 클라이언트 인스턴스에서 등록\n // client(existingMcpClient)\n }\n }\n}\n```\n\n## 왜 Koog + Ktor인가요?\n\n- 서버에서 에이전트를 개발하기 위한 Kotlin 우선의 타입 안전한 환경\n- 깔끔하고 테스트 가능한 라우트 코드와 중앙 집중식 설정\n- 라우트별로 적합한 모델을 사용하거나, 직접 LLM 호출 시 자동으로 폴백 적용\n- 도구(tools), 모데레이션(moderation), 스트리밍(streaming), 트레이싱(tracing) 등 프로덕션 환경에 적합한 기능 제공"}, "93d8eaa8d1c65ff83767f812ce3d318862abb0d2": {"t": 1785764920.956403, "n": 6748, "h": "8d555d75907a305b", "c": "# Ktor 통합: Koog 플러그인\n\nKoog는 Ktor 서버에 자연스럽게 통합되어 양쪽에서 관용적인 Kotlin API를 사용하여 서버 측 AI 애플리케이션을 작성할 수 있게 합니다.\n\nKoog 플러그인을 한 번 설치하고, `application.conf` 또는 `application.yaml` 파일이나 코드에서 LLM 공급자를 구성한 다음, 라우트에서 직접 에이전트를 호출할 수 있습니다. 더 이상 모듈 간에 LLM 클라이언트를 연결할 필요 없이, 라우트에서 에이전트를 요청하기만 하면 준비 완료입니다.\n\n## 개요\n\n`koog-ktor` 모듈은 서버 측 에이전트 개발을 위한 관용적인 Kotlin/Ktor 통합 기능을 제공합니다:\n\n- 드롭인 Ktor 플러그인: `Application`에서 `install(Koog)`\n- OpenAI, Anthropic, Google, OpenRouter, DeepSeek 및 Ollama에 대한 일급 지원\n- YAML/CONF 및/또는 코드를 통한 중앙 집중식 구성\n- 프롬프트, 도구, 기능으로 에이전트 설정; 라우트를 위한 간단한 확장 함수\n- 직접 LLM 사용 (`execute`, `executeStreaming`, `moderate`)\n- JVM 전용 Model Context Protocol (MCP) 도구 통합\n\n## 의존성 추가\n\n```kotlin\ndependencies {\n implementation(\"ai.koog:koog-ktor:$koogVersion\")\n}\n```\n\n## 빠른 시작\n\n1) 공급자 구성 (`application.yaml` 또는 `application.conf` 파일에서)\n\n`koog.<provider>` 아래에 중첩된 키를 사용하세요. 플러그인이 자동으로 이를 감지합니다.\n\n```yaml\n# application.yaml (Ktor config)\nkoog:\n openai:\n apikey: ${OPENAI_API_KEY}\n baseUrl: https://api.openai.com\n anthropic:\n apikey: ${ANTHROPIC_API_KEY}\n baseUrl: https://api.anthropic.com\n google:\n apikey: ${GOOGLE_API_KEY}\n baseUrl: https://generativelanguage.googleapis.com\n openrouter:\n apikey: ${OPENROUTER_API_KEY}\n baseUrl: https://openrouter.ai\n deepseek:\n apikey: ${DEEPSEEK_API_KEY}\n baseUrl: https://api.deepseek.com\n # Ollama is enabled when any koog.ollama.* key exists\n ollama:\n enable: true\n baseUrl: http://localhost:11434\n```\n\n선택 사항: 요청된 공급자가 구성되지 않았을 때 직접 LLM 호출에서 사용되는 폴백(fallback)을 구성합니다.\n\n```yaml\nkoog:\n llm:\n fallback:\n provider: openai\n # see Model identifiers section below\n model: openai.chat.gpt4_1\n```\n\n2) 플러그인 설치 및 라우트 정의\n\n```kotlin\nfun Application.module() {\n install(Koog) {\n // You can also configure providers programmatically (see below)\n }\n\n routing {\n route(\"/ai\") {\n post(\"/chat\") {\n val userInput = call.receiveText()\n // Create and run a default single‑run agent using a specific model\n val output = aiAgent(\n strategy = reActStrategy(),\n model = OpenAIModels.Chat.GPT4_1,\n input = userInput\n )\n call.respond(HttpStatusCode.OK, output)\n }\n }\n }\n}\n```\n\n참고\n\n- `aiAgent`는 구체적인 모델(`LLModel`)을 필요로 합니다. 라우트별, 사용별로 선택하세요.\n- 하위 레벨 LLM 접근을 위해서는 `llm() (PromptExecutor)`를 직접 사용하세요.\n\n## 라우트에서 직접 LLM 사용\n\n```kotlin\npost(\"/llm-chat\") {\n val userInput = call.receiveText()\n\n val messages = llm().execute(\n prompt(\"chat\") {\n system(\"You are a helpful assistant that clarifies questions\")\n user(userInput)\n },\n GoogleModels.Gemini2_5Pro\n )\n\n // Join all assistant messages into a single string\n val text = messages.joinToString(separator = \"\") { it.content }\n call.respond(HttpStatusCode.OK, text)\n}\n```\n\n스트리밍\n\n```kotlin\nget(\"/stream\") {\n val flow = llm().executeStreaming(\n prompt(\"streaming\") { user(\"Stream this response, please\") },\n OpenRouterModels.GPT4o\n )\n\n // Example: buffer and send as one chunk\n val sb = StringBuilder()\n flow.collect { chunk -> sb.append(chunk) }\n call.respondText(sb.toString())\n}\n```\n\n중재 (Moderation)\n\n```kotlin\npost(\"/moderated-chat\") {\n val userInput = call.receiveText()\n\n val moderation = llm().moderate(\n prompt(\"moderation\") { user(userInput) },\n OpenAIModels.Moderation.Omni\n )\n\n if (moderation.isHarmful) {\n call.respond(HttpStatusCode.BadRequest, \"Harmful content detected\")\n return@post\n }\n\n val output = aiAgent(\n strategy = reActStrategy(),\n model = OpenAIModels.Chat.GPT4_1,\n input = userInput\n )\n call.respond(HttpStatusCode.OK, output)\n}\n```\n\n## 프로그래밍 방식 구성 (코드 내)\n\n모든 공급자 및 에이전트 동작은 `install(Koog) {}`를 통해 구성할 수 있습니다.\n\n```kotlin\ninstall(Koog) {\n llm {\n openAI(apiKey = System.getenv(\"OPENAI_API_KEY\") ?: \"\") {\n baseUrl = \"https://api.openai.com\"\n timeouts { // Default values shown below\n requestTimeout = 15.minutes\n connectTimeout = 60.seconds\n socketTimeout = 15.minutes\n }\n }\n anthropic(apiKey = System.getenv(\"ANTHROPIC_API_KEY\") ?: \"\")\n google(apiKey = System.getenv(\"GOOGLE_API_KEY\") ?: \"\")\n openRouter(apiKey = System.getenv(\"OPENROUTER_API_KEY\") ?: \"\")\n deepSeek(apiKey = System.getenv(\"DEEPSEEK_API_KEY\") ?: \"\")\n ollama { baseUrl = \"http://localhost:11434\" }\n\n // Optional fallback used by PromptExecutor when a provider isn’t configured\n fallback {\n provider = LLMProvider.OpenAI\n model = OpenAIModels.Chat.GPT4_1\n }\n }\n\n agentConfig {\n // Provide a reusable base prompt for your agents\n prompt(name = \"agent\") {\n system(\"You are a helpful server‑side agent\")\n }\n\n // Limit runaway tools/loops\n maxAgentIterations = 10\n\n // Register tools available to agents by default\n registerTools {\n // tool(::yourTool) // see Tools Overview for details\n }\n\n // Install agent features (tracing, etc.)\n // install(OpenTelemetry) { /* ... */ }\n }\n}\n```\n\n## 구성 (폴백) 내 모델 식별자\n\nYAML/CONF에서 `llm.fallback`을 구성할 때는 다음 식별자 형식을 사용하세요.\n\n- OpenAI: `openai.chat.gpt4_1`, `openai.reasoning.o3`, `openai.costoptimized.gpt4_1mini`, `openai.audio.gpt4oaudio`, `openai.moderation.omni`\n- Anthropic: `anthropic.sonnet_3_7`, `anthropic.opus_4`, `anthropic.haiku_3_5`\n- Google: `google.gemini2_5pro`, `google.gemini2_0flash001`\n- OpenRouter: `openrouter.gpt4o`, `openrouter.gpt4`, `openrouter.claude3sonnet`\n- DeepSeek: `deepseek.deepseek-chat`, `deepseek.deepseek-reasoner`\n- Ollama: `ollama.meta.llama3.2`, `ollama.alibaba.qwq:32b`, `ollama.groq.llama3-grok-tool-use:8b`\n\n참고\n\n- OpenAI의 경우 카테고리(`chat`, `reasoning`, `costoptimized`, `audio`, `embeddings`, `moderation`)를 반드시 포함해야 합니다.\n- Ollama의 경우, `ollama.model` 및 `ollama.<maker>.<model>` 모두 지원됩니다.\n\n## MCP 도구 (JVM 전용)\n\nJVM에서는 MCP 서버의 도구를 에이전트 도구 레지스트리에 추가할 수 있습니다:\n\n```kotlin\ninstall(Koog) {\n agentConfig {\n mcp {\n // Register via SSE\n sse(\"https://your-mcp-server.com/sse\")\n\n // Or register via spawned process (stdio transport)\n // process(Runtime.getRuntime().exec(\"your-mcp-binary ...\"))\n\n // Or from an existing MCP client instance\n // client(existingMcpClient)\n }\n }\n}\n```\n## Koog + Ktor를 사용하는 이유?\n\n- Kotlin 우선의, 타입 세이프(type-safe)한 서버 내 에이전트 개발\n- 깔끔하고 테스트 가능한 라우트 코드와 중앙 집중식 구성\n- 라우트별로 적절한 모델을 사용하거나, 직접 LLM 호출 시 자동으로 폴백 사용\n- 프로덕션 준비 완료 기능: 도구, 중재(moderation), 스트리밍 및 추적(tracing)"}, "acc53f4a0a97c09d2eae93ab29cefc590d6b6ea3": {"t": 1785764922.6345131, "n": 6745, "h": "8bcaad5458d35085", "c": "# Ktor 통합: Koog 플러그인\n\nKoog는 Ktor 서버에 자연스럽게 통합되어 양쪽에서 관용적인 Kotlin API를 사용하여 서버 측 AI 애플리케이션을 작성할 수 있게 합니다.\n\nKoog 플러그인을 한 번 설치하고, `application.conf` 또는 `application.yaml` 파일이나 코드에서 LLM 공급자를 구성한 다음, 라우트에서 직접 에이전트를 호출할 수 있습니다. 더 이상 모듈 간에 LLM 클라이언트를 연결할 필요 없이, 라우트에서 에이전트를 요청하기만 하면 준비 완료입니다.\n\n## 개요\n\n`koog-ktor` 모듈은 서버 측 에이전트 개발을 위한 관용적인 Kotlin/Ktor 통합 기능을 제공합니다:\n\n- 드롭인 Ktor 플러그인: `Application`에서 `install(Koog)`\n- OpenAI, Anthropic, Google, OpenRouter, DeepSeek 및 Ollama에 대한 일급 지원\n- YAML/CONF 및/또는 코드를 통한 중앙 집중식 구성\n- 프롬프트, 도구, 기능으로 에이전트 설정; 라우트를 위한 간단한 확장 함수\n- 직접 LLM 사용 (`execute`, `executeStreaming`, `moderate`)\n- JVM 전용 Model Context Protocol (MCP) 도구 통합\n\n## 의존성 추가\n\n```kotlin\ndependencies {\n implementation(\"ai.koog:koog-ktor:$koogVersion\")\n}\n```\n\n## 빠른 시작\n\n1) 공급자 구성 (`application.yaml` 또는 `application.conf` 파일에서)\n\n`koog.<provider>` 아래에 중첩된 키를 사용하세요. 플러그인이 자동으로 이를 감지합니다.\n\n```yaml\n# application.yaml (Ktor config)\nkoog:\n openai:\n apikey: ${OPENAI_API_KEY}\n baseUrl: https://api.openai.com\n anthropic:\n apikey: ${ANTHROPIC_API_KEY}\n baseUrl: https://api.anthropic.com\n google:\n apikey: ${GOOGLE_API_KEY}\n baseUrl: https://generativelanguage.googleapis.com\n openrouter:\n apikey: ${OPENROUTER_API_KEY}\n baseUrl: https://openrouter.ai\n deepseek:\n apikey: ${DEEPSEEK_API_KEY}\n baseUrl: https://api.deepseek.com\n # Ollama is enabled when any koog.ollama.* key exists\n ollama:\n enable: true\n baseUrl: http://localhost:11434\n```\n\n선택 사항: 요청된 공급자가 구성되지 않았을 때 직접 LLM 호출에서 사용되는 폴백(fallback)을 구성합니다.\n\n```yaml\nkoog:\n llm:\n fallback:\n provider: openai\n # see Model identifiers section below\n model: openai.chat.gpt4_1\n```\n\n2) 플러그인 설치 및 라우트 정의\n\n```kotlin\nfun Application.module() {\n install(Koog) {\n // You can also configure providers programmatically (see below)\n }\n\n routing {\n route(\"/ai\") {\n post(\"/chat\") {\n val userInput = call.receiveText()\n // Create and run a default single‑run agent using a specific model\n val output = aiAgent(\n strategy = reActStrategy(),\n model = OpenAIModels.Chat.GPT4_1,\n input = userInput\n )\n call.respond(HttpStatusCode.OK, output)\n }\n }\n }\n}\n```\n\n참고\n- `aiAgent`는 구체적인 모델(`LLModel`)을 필요로 합니다. 라우트별, 사용별로 선택하세요.\n- 하위 레벨 LLM 접근을 위해서는 `llm() (PromptExecutor)`를 직접 사용하세요.\n\n## 라우트에서 직접 LLM 사용\n\n```kotlin\npost(\"/llm-chat\") {\n val userInput = call.receiveText()\n\n val messages = llm().execute(\n prompt(\"chat\") {\n system(\"You are a helpful assistant that clarifies questions\")\n user(userInput)\n },\n GoogleModels.Gemini2_5Pro\n )\n\n // Join all assistant messages into a single string\n val text = messages.joinToString(separator = \"\") { it.content }\n call.respond(HttpStatusCode.OK, text)\n}\n```\n\n스트리밍\n\n```kotlin\nget(\"/stream\") {\n val flow = llm().executeStreaming(\n prompt(\"streaming\") { user(\"Stream this response, please\") },\n OpenRouterModels.GPT4o\n )\n\n // Example: buffer and send as one chunk\n val sb = StringBuilder()\n flow.collect { chunk -> sb.append(chunk) }\n call.respondText(sb.toString())\n}\n```\n\n중재 (Moderation)\n\n```kotlin\npost(\"/moderated-chat\") {\n val userInput = call.receiveText()\n\n val moderation = llm().moderate(\n prompt(\"moderation\") { user(userInput) },\n OpenAIModels.Moderation.Omni\n )\n\n if (moderation.isHarmful) {\n call.respond(HttpStatusCode.BadRequest, \"Harmful content detected\")\n return@post\n }\n\n val output = aiAgent(\n strategy = reActStrategy(),\n model = OpenAIModels.Chat.GPT4_1,\n input = userInput\n )\n call.respond(HttpStatusCode.OK, output)\n}\n```\n\n## 프로그래밍 방식 구성 (코드 내)\n\n모든 공급자 및 에이전트 동작은 `install(Koog) {}`를 통해 구성할 수 있습니다.\n\n```kotlin\ninstall(Koog) {\n llm {\n openAI(apiKey = System.getenv(\"OPENAI_API_KEY\") ?: \"\") {\n baseUrl = \"https://api.openai.com\"\n timeouts { // Default values shown below\n requestTimeout = 15.minutes\n connectTimeout = 60.seconds\n socketTimeout = 15.minutes\n }\n }\n anthropic(apiKey = System.getenv(\"ANTHROPIC_API_KEY\") ?: \"\")\n google(apiKey = System.getenv(\"GOOGLE_API_KEY\") ?: \"\")\n openRouter(apiKey = System.getenv(\"OPENROUTER_API_KEY\") ?: \"\")\n deepSeek(apiKey = System.getenv(\"DEEPSEEK_API_KEY\") ?: \"\")\n ollama { baseUrl = \"http://localhost:11434\" }\n\n // Optional fallback used by PromptExecutor when a provider isn’t configured\n fallback {\n provider = LLMProvider.OpenAI\n model = OpenAIModels.Chat.GPT4_1\n }\n }\n\n agentConfig {\n // Provide a reusable base prompt for your agents\n prompt(name = \"agent\") {\n system(\"You are a helpful server‑side agent\")\n }\n\n // Limit runaway tools/loops\n maxAgentIterations = 10\n\n // Register tools available to agents by default\n registerTools {\n // tool(::yourTool) // see Tools Overview for details\n }\n\n // Install agent features (tracing, etc.)\n // install(OpenTelemetry) { /* ... */ }\n }\n}\n```\n\n## 구성 (폴백) 내 모델 식별자\n\nYAML/CONF에서 `llm.fallback`을 구성할 때는 다음 식별자 형식을 사용하세요.\n- OpenAI: `openai.chat.gpt4_1`, `openai.reasoning.o3`, `openai.costoptimized.gpt4_1mini`, `openai.audio.gpt4oaudio`, `openai.moderation.omni`\n- Anthropic: `anthropic.sonnet_3_7`, `anthropic.opus_4`, `anthropic.haiku_3_5`\n- Google: `google.gemini2_5pro`, `google.gemini2_0flash001`\n- OpenRouter: `openrouter.gpt4o`, `openrouter.gpt4`, `openrouter.claude3sonnet`\n- DeepSeek: `deepseek.deepseek-chat`, `deepseek.deepseek-reasoner`\n- Ollama: `ollama.meta.llama3.2`, `ollama.alibaba.qwq:32b`, `ollama.groq.llama3-grok-tool-use:8b`\n\n참고\n- OpenAI의 경우 카테고리(`chat`, `reasoning`, `costoptimized`, `audio`, `embeddings`, `moderation`)를 반드시 포함해야 합니다.\n- Ollama의 경우, `ollama.model` 및 `ollama.<maker>.<model>` 모두 지원됩니다.\n\n## MCP 도구 (JVM 전용)\n\nJVM에서는 MCP 서버의 도구를 에이전트 도구 레지스트리에 추가할 수 있습니다:\n\n```kotlin\ninstall(Koog) {\n agentConfig {\n mcp {\n // Register via SSE\n sse(\"https://your-mcp-server.com/sse\")\n\n // Or register via spawned process (stdio transport)\n // process(Runtime.getRuntime().exec(\"your-mcp-binary ...\"))\n\n // Or from an existing MCP client instance\n // client(existingMcpClient)\n }\n }\n}\n```\n## Koog + Ktor를 사용하는 이유?\n\n- Kotlin 우선의, 타입 세이프(type-safe)한 서버 내 에이전트 개발\n- 깔끔하고 테스트 가능한 라우트 코드와 중앙 집중식 구성\n- 라우트별로 적절한 모델을 사용하거나, 직접 LLM 호출 시 자동으로 폴백 사용\n- 프로덕션 준비 완료 기능: 도구, 중재(moderation), 스트리밍 및 추적(tracing)"}, "3a1f4caaf01fdf5089e5c769be4f71af1e5a8967": {"t": 1785764924.6220272, "n": 6770, "h": "5ef7b2b9a7d3bbb7", "c": "# Ktor 통합: Koog 플러그인\n\nKoog는 Ktor 서버에 자연스럽게 통합되어 양쪽에서 관용적인 Kotlin API를 사용하여 서버 측 AI 애플리케이션을 작성할 수 있게 합니다.\n\nKoog 플러그인을 한 번 설치하고, `application.conf` 또는 `application.yaml` 파일이나 코드에서 LLM (Large Language Model) 공급자를 구성한 다음, 라우트에서 직접 에이전트를 호출할 수 있습니다. 더 이상 모듈 간에 LLM 클라이언트를 연결할 필요 없이, 라우트에서 에이전트를 요청하기만 하면 준비 완료입니다.\n\n## 개요\n\n`koog-ktor` 모듈은 서버 측 에이전트 개발을 위한 관용적인 Kotlin/Ktor 통합 기능을 제공합니다:\n\n- 드롭인 Ktor 플러그인: `Application`에서 `install(Koog)`\n- OpenAI, Anthropic, Google, OpenRouter, DeepSeek 및 Ollama에 대한 일급 지원\n- YAML/CONF 및/또는 코드를 통한 중앙 집중식 구성\n- 프롬프트, 도구, 기능으로 에이전트 설정; 라우트를 위한 간단한 확장 함수\n- 직접 LLM 사용 (`execute`, `executeStreaming`, `moderate`)\n- JVM 전용 Model Context Protocol (MCP) 도구 통합\n\n## 의존성 추가\n\n```kotlin\ndependencies {\n implementation(\"ai.koog:koog-ktor:$koogVersion\")\n}\n```\n\n## 빠른 시작\n\n1) 공급자 구성 (`application.yaml` 또는 `application.conf` 파일에서)\n\n`koog.<provider>` 아래에 중첩된 키를 사용하세요. 플러그인이 자동으로 이를 감지합니다.\n\n```yaml\n# application.yaml (Ktor config)\nkoog:\n openai:\n apikey: ${OPENAI_API_KEY}\n baseUrl: https://api.openai.com\n anthropic:\n apikey: ${ANTHROPIC_API_KEY}\n baseUrl: https://api.anthropic.com\n google:\n apikey: ${GOOGLE_API_KEY}\n baseUrl: https://generativelanguage.googleapis.com\n openrouter:\n apikey: ${OPENROUTER_API_KEY}\n baseUrl: https://openrouter.ai\n deepseek:\n apikey: ${DEEPSEEK_API_KEY}\n baseUrl: https://api.deepseek.com\n # Ollama is enabled when any koog.ollama.* key exists\n ollama:\n enable: true\n baseUrl: http://localhost:11434\n```\n\n선택 사항: 요청된 공급자가 구성되지 않았을 때 직접 LLM 호출에서 사용되는 폴백(fallback)을 구성합니다.\n\n```yaml\nkoog:\n llm:\n fallback:\n provider: openai\n # see Model identifiers section below\n model: openai.chat.gpt4_1\n```\n\n2) 플러그인 설치 및 라우트 정의\n\n```kotlin\nfun Application.module() {\n install(Koog) {\n // You can also configure providers programmatically (see below)\n }\n\n routing {\n route(\"/ai\") {\n post(\"/chat\") {\n val userInput = call.receiveText()\n // Create and run a default single‑run agent using a specific model\n val output = aiAgent(\n strategy = reActStrategy(),\n model = OpenAIModels.Chat.GPT4_1,\n input = userInput\n )\n call.respond(HttpStatusCode.OK, output)\n }\n }\n }\n}\n```\n\n참고:\n- `aiAgent`는 구체적인 모델(`LLModel`)을 필요로 합니다. 라우트별, 사용별로 선택하세요.\n- 하위 레벨 LLM 접근을 위해서는 `llm() (PromptExecutor)`를 직접 사용하세요.\n\n## 라우트에서 직접 LLM 사용\n\n```kotlin\npost(\"/llm-chat\") {\n val userInput = call.receiveText()\n\n val messages = llm().execute(\n prompt(\"chat\") {\n system(\"You are a helpful assistant that clarifies questions\")\n user(userInput)\n },\n GoogleModels.Gemini2_5Pro\n )\n\n // Join all assistant messages into a single string\n val text = messages.joinToString(separator = \"\") { it.content }\n call.respond(HttpStatusCode.OK, text)\n}\n```\n\n스트리밍\n\n```kotlin\nget(\"/stream\") {\n val flow = llm().executeStreaming(\n prompt(\"streaming\") { user(\"Stream this response, please\") },\n OpenRouterModels.GPT4o\n )\n\n // Example: buffer and send as one chunk\n val sb = StringBuilder()\n flow.collect { chunk -> sb.append(chunk) }\n call.respondText(sb.toString())\n}\n```\n\n중재 (Moderation)\n\n```kotlin\npost(\"/moderated-chat\") {\n val userInput = call.receiveText()\n\n val moderation = llm().moderate(\n prompt(\"moderation\") { user(userInput) },\n OpenAIModels.Moderation.Omni\n )\n\n if (moderation.isHarmful) {\n call.respond(HttpStatusCode.BadRequest, \"Harmful content detected\")\n return@post\n }\n\n val output = aiAgent(\n strategy = reActStrategy(),\n model = OpenAIModels.Chat.GPT4_1,\n input = userInput\n )\n call.respond(HttpStatusCode.OK, output)\n}\n```\n\n## 프로그래밍 방식 구성 (코드 내)\n\n모든 공급자 및 에이전트 동작은 `install(Koog) {}`를 통해 구성할 수 있습니다.\n\n```kotlin\ninstall(Koog) {\n llm {\n openAI(apiKey = System.getenv(\"OPENAI_API_KEY\") ?: \"\") {\n baseUrl = \"https://api.openai.com\"\n timeouts { // Default values shown below\n requestTimeout = 15.minutes\n connectTimeout = 60.seconds\n socketTimeout = 15.minutes\n }\n }\n anthropic(apiKey = System.getenv(\"ANTHROPIC_API_KEY\") ?: \"\")\n google(apiKey = System.getenv(\"GOOGLE_API_KEY\") ?: \"\")\n openRouter(apiKey = System.getenv(\"OPENROUTER_API_KEY\") ?: \"\")\n deepSeek(apiKey = System.getenv(\"DEEPSEEK_API_KEY\") ?: \"\")\n ollama { baseUrl = \"http://localhost:11434\" }\n\n // Optional fallback used by PromptExecutor when a provider isn’t configured\n fallback {\n provider = LLMProvider.OpenAI\n model = OpenAIModels.Chat.GPT4_1\n }\n }\n\n agentConfig {\n // Provide a reusable base prompt for your agents\n prompt(name = \"agent\") {\n system(\"You are a helpful server‑side agent\")\n }\n\n // Limit runaway tools/loops\n maxAgentIterations = 10\n\n // Register tools available to agents by default\n registerTools {\n // tool(::yourTool) // see Tools Overview for details\n }\n\n // Install agent features (tracing, etc.)\n // install(OpenTelemetry) { /* ... */ }\n }\n}\n```\n\n## 구성 (폴백) 내 모델 식별자\n\nYAML/CONF에서 `llm.fallback`을 구성할 때는 다음 식별자 형식을 사용하세요.\n- OpenAI: `openai.chat.gpt4_1`, `openai.reasoning.o3`, `openai.costoptimized.gpt4_1mini`, `openai.audio.gpt4oaudio`, `openai.moderation.omni`\n- Anthropic: `anthropic.sonnet_3_7`, `anthropic.opus_4`, `anthropic.haiku_3_5`\n- Google: `google.gemini2_5pro`, `google.gemini2_0flash001`\n- OpenRouter: `openrouter.gpt4o`, `openrouter.gpt4`, `openrouter.claude3sonnet`\n- DeepSeek: `deepseek.deepseek-chat`, `deepseek.deepseek-reasoner`\n- Ollama: `ollama.meta.llama3.2`, `ollama.alibaba.qwq:32b`, `ollama.groq.llama3-grok-tool-use:8b`\n\n참고:\n- OpenAI의 경우 카테고리(`chat`, `reasoning`, `costoptimized`, `audio`, `embeddings`, `moderation`)를 반드시 포함해야 합니다.\n- Ollama의 경우 `ollama.model` 및 `ollama.<maker>.<model>` 모두 지원됩니다.\n\n## MCP 도구 (JVM 전용)\n\nJVM에서는 MCP 서버에서 도구를 에이전트 도구 레지스트리에 추가할 수 있습니다:\n\n```kotlin\ninstall(Koog) {\n agentConfig {\n mcp {\n // Register via SSE\n sse(\"https://your-mcp-server.com/sse\")\n\n // Or register via spawned process (stdio transport)\n // process(Runtime.getRuntime().exec(\"your-mcp-binary ...\"))\n\n // Or from an existing MCP client instance\n // client(existingMcpClient)\n }\n }\n}\n```\n## Koog + Ktor를 사용하는 이유?\n\n- Kotlin 우선의, 타입 세이프(type-safe)한 서버 내 에이전트 개발\n- 깔끔하고 테스트 가능한 라우트 코드와 중앙 집중식 구성\n- 라우트별로 적절한 모델을 사용하거나, 직접 LLM 호출 시 자동으로 폴백 사용\n- 프로덕션 준비 완료 기능: 도구, 중재(moderation), 스트리밍 및 추적(tracing)"}, "e1d711bc2020b356cd17bac6bbd4e23dc8e60599": {"t": 1786067793.1569705, "n": 6691, "h": "1ca6797758fe2afe", "c": "---\nstatus: beta\n---\n\n# Ktor 통합: Koog 플러그인\n\n--8<-- \"versioning-snippets.md:beta\"\n\nKoog는 Ktor 서버에 자연스럽게 통합되어, 양측 모두에서 관용적인(idiomatic) Kotlin API를 사용하여 서버 사이드 AI 애플리케이션을 작성할 수 있게 해줍니다.\n\nKoog 플러그인을 한 번 설치하고, `application.conf`/`YAML` 또는 코드에서 LLM 제공자(provider)를 설정한 다음 라우트(route)에서 바로 에이전트를 호출하세요. 더 이상 모듈 간에 LLM 클라이언트를 복잡하게 연결할 필요가 없습니다. 라우트에서 에이전트를 요청하기만 하면 바로 사용할 준비가 됩니다.\n\n## 개요\n\n`koog-ktor` 모듈은 서버 사이드 에이전트(agentic) 개발을 위한 관용적인 Kotlin/Ktor 통합 기능을 제공합니다.\n\n- 바로 사용 가능한 Ktor 플러그인: Application에서 `install(Koog)` 호출\n- OpenAI, Anthropic, Google, OpenRouter, DeepSeek, Ollama에 대한 최고 수준의 지원\n- YAML/CONF 및 코드를 통한 중앙 집중식 설정\n- 프롬프트, 도구, 기능을 포함한 에이전트 설정 및 라우트를 위한 간단한 확장 함수\n- 직접적인 LLM 사용 (`execute`, `executeStreaming`, `moderate`)\n- JVM 전용 MCP(Model Context Protocol) 도구 통합\n\n## 의존성 추가\n\n```kotlin\ndependencies {\n implementation(\"ai.koog:koog-ktor:$koogVersion\")\n}\n```\n\n## 빠른 시작\n\n1) 제공자 설정 (`application.yaml` 또는 `application.conf`)\n\n`koog.<provider>` 아래의 중첩된 키를 사용하세요. 플러그인이 자동으로 이를 인식합니다.\n\n```yaml\n# application.yaml (Ktor 설정)\nkoog:\n openai:\n apikey: ${OPENAI_API_KEY}\n baseUrl: https://api.openai.com\n anthropic:\n apikey: ${ANTHROPIC_API_KEY}\n baseUrl: https://api.anthropic.com\n google:\n apikey: ${GOOGLE_API_KEY}\n baseUrl: https://generativelanguage.googleapis.com\n openrouter:\n apikey: ${OPENROUTER_API_KEY}\n baseUrl: https://openrouter.ai\n deepseek:\n apikey: ${DEEPSEEK_API_KEY}\n baseUrl: https://api.deepseek.com\n # koog.ollama.* 키가 존재하면 Ollama가 활성화됩니다.\n ollama:\n enable: true\n baseUrl: http://localhost:11434\n```\n\n선택 사항: 요청된 제공자가 설정되지 않았을 때 직접 LLM 호출에서 사용할 폴백(fallback)을 설정합니다.\n\n```yaml\nkoog:\n llm:\n fallback:\n provider: openai\n # 아래의 모델 식별자 섹션을 참조하세요.\n model: openai.chat.gpt4_1\n```\n\n2) 플러그인 설치 및 라우트 정의\n\n```kotlin\nfun Application.module() {\n install(Koog) {\n // 프로그래밍 방식으로 제공자를 설정할 수도 있습니다 (아래 참조)\n }\n\n routing {\n route(\"/ai\") {\n post(\"/chat\") {\n val userInput = call.receiveText()\n // 특정 모델을 사용하여 기본 단일 실행 에이전트를 생성하고 실행합니다.\n val output = aiAgent(\n strategy = reActStrategy(),\n model = OpenAIModels.Chat.GPT4_1,\n input = userInput\n )\n call.respond(HttpStatusCode.OK, output)\n }\n }\n }\n}\n```\n\n참고\n\n- `aiAgent`는 구체적인 모델(`LLModel`)이 필요합니다. 라우트별 또는 용도별로 선택하세요.\n- 더 낮은 수준의 LLM 액세스가 필요한 경우, `llm()`(`PromptExecutor`)을 직접 사용하세요.\n\n## 라우트에서 직접 LLM 사용\n\n```kotlin\npost(\"/llm-chat\") {\n val userInput = call.receiveText()\n\n val messages = llm().execute(\n prompt(\"chat\") {\n system(\"You are a helpful assistant that clarifies questions\")\n user(userInput)\n },\n GoogleModels.Gemini2_5Pro\n )\n\n // 모든 어시스턴트 메시지를 하나의 문자열로 결합합니다.\n val text = messages.joinToString(separator = \"\n\") { it.content }\n call.respond(HttpStatusCode.OK, text)\n}\n```\n\n스트리밍(Streaming)\n\n```kotlin\nget(\"/stream\") {\n val flow = llm().executeStreaming(\n prompt(\"streaming\") { user(\"Stream this response, please\") },\n OpenRouterModels.GPT4o\n )\n\n // 예시: 버퍼링 후 하나의 청크로 전송\n val sb = StringBuilder()\n flow.collect { chunk -> sb.append(chunk) }\n call.respondText(sb.toString())\n}\n```\n\n모데레이션(Moderation)\n\n```kotlin\npost(\"/moderated-chat\") {\n val userInput = call.receiveText()\n\n val moderation = llm().moderate(\n prompt(\"moderation\") { user(userInput) },\n OpenAIModels.Moderation.Omni\n )\n\n if (moderation.isHarmful) {\n call.respond(HttpStatusCode.BadRequest, \"Harmful content detected\")\n return@post\n }\n\n val output = aiAgent(\n strategy = reActStrategy(),\n model = OpenAIModels.Chat.GPT4_1,\n input = userInput\n )\n call.respond(HttpStatusCode.OK, output)\n}\n```\n\n## 프로그래밍 방식 설정 (코드 내)\n\n모든 제공자와 에이전트 동작은 `install(Koog) {}`를 통해 설정할 수 있습니다.\n\n```kotlin\ninstall(Koog) {\n llm {\n openAI(apiKey = System.getenv(\"OPENAI_API_KEY\") ?: \"\") {\n baseUrl = \"https://api.openai.com\"\n timeouts { // 아래는 기본값입니다.\n requestTimeout = 15.minutes\n connectTimeout = 60.seconds\n socketTimeout = 15.minutes\n }\n }\n anthropic(apiKey = System.getenv(\"ANTHROPIC_API_KEY\") ?: \"\")\n google(apiKey = System.getenv(\"GOOGLE_API_KEY\") ?: \"\")\n openRouter(apiKey = System.getenv(\"OPENROUTER_API_KEY\") ?: \"\")\n deepSeek(apiKey = System.getenv(\"DEEPSEEK_API_KEY\") ?: \"\")\n ollama { baseUrl = \"http://localhost:11434\" }\n\n // 제공자가 설정되지 않았을 때 PromptExecutor에서 사용할 선택적 폴백\n fallback {\n provider = LLMProvider.OpenAI\n model = OpenAIModels.Chat.GPT4_1\n }\n }\n\n agentConfig {\n // 에이전트를 위한 재사용 가능한 기본 프롬프트 제공\n prompt(name = \"agent\") {\n system(\"You are a helpful server‑side agent\")\n }\n\n // 무한 도구 호출/루프 제한\n maxAgentIterations = 10\n\n // 에이전트가 기본적으로 사용할 수 있는 도구 등록\n registerTools {\n // tool(::yourTool) // 자세한 내용은 도구 개요를 참조하세요.\n }\n\n // 에이전트 기능 설치 (트레이싱 등)\n // install(OpenTelemetry) { /* ... */ }\n }\n}\n```\n\n## 설정 내 모델 식별자 (폴백)\n\nYAML/CONF에서 `llm.fallback`을 설정할 때 다음 식별자 형식을 사용하세요.\n\n- OpenAI: `openai.chat.gpt4_1`, `openai.reasoning.o3`, `openai.costoptimized.gpt4_1mini`, `openai.audio.gpt4oaudio`, `openai.moderation.omni`\n- Anthropic: `anthropic.fable_5`, `anthropic.sonnet_4_5`, `anthropic.opus_4`, `anthropic.haiku_4_5`\n- Google: `google.gemini2_5pro`, `google.gemini2_0flash001`\n- OpenRouter: `openrouter.gpt4o`, `openrouter.gpt4`, `openrouter.claude3sonnet`\n- DeepSeek: `deepseek.deepseek-v4-flash`, `deepseek.deepseek-v4-pro`, `deepseek.deepseek-chat`, `deepseek.deepseek-reasoner`\n- Ollama: `ollama.meta.llama3.2`, `ollama.alibaba.qwq:32b`, `ollama.groq.llama3-grok-tool-use:8b`\n\n참고\n\n- OpenAI의 경우 반드시 카테고리(`chat`, `reasoning`, `costoptimized`, `audio`, `embeddings`, `moderation`)를 포함해야 합니다.\n- Ollama의 경우 `ollama.model` 및 `ollama.<maker>.<model>` 형식을 모두 지원합니다.\n\n## MCP 도구 (JVM 전용)\n\nJVM에서는 MCP 서버의 도구를 에이전트 도구 레지스트리에 추가할 수 있습니다.\n\n```kotlin\ninstall(Koog) {\n agentConfig {\n mcp {\n // SSE를 통해 등록\n sse(\"https://your-mcp-server.com/sse\")\n\n // 또는 생성된 프로세스를 통해 등록 (stdio 전송)\n // process(Runtime.getRuntime().exec(\"your-mcp-binary ...\"))\n\n // 또는 기존 MCP 클라이언트 인스턴스에서 등록\n // client(existingMcpClient)\n }\n }\n}\n```\n## 왜 Koog + Ktor인가요?\n\n- 서버에서 에이전트를 개발하기 위한 Kotlin 우선의 타입 안전한 환경\n- 깔끔하고 테스트 가능한 라우트 코드와 중앙 집중식 설정\n- 라우트별로 적합한 모델을 사용하거나, 직접 LLM 호출 시 자동으로 폴백 적용\n- 도구(tools), 모데레이션(moderation), 스트리밍(streaming), 트레이싱(tracing) 등 프로덕션 환경에 적합한 기능 제공"}}}}