์ฝ˜ํ…์ธ ๋กœ ์ด๋™

API ์„œ๋ฒ„ ์‚ฌ์šฉํ•˜๊ธฐ

ADK์—์„œ ์ง€์›Python v0.1.0TypeScript v0.2.0Go v0.1.0Java v0.1.0

์—์ด์ „ํŠธ๋ฅผ ๋ฐฐํฌํ•˜๊ธฐ ์ „์— ์˜๋„ํ•œ ๋Œ€๋กœ ์ž‘๋™ํ•˜๋Š”์ง€ ํ…Œ์ŠคํŠธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ ์—์ด์ „ํŠธ๋ฅผ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ฐ€์žฅ ์‰ฌ์šด ๋ฐฉ๋ฒ•์€ ADK API ์„œ๋ฒ„๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

adk api_server
go run agent.go web api

ํฌํŠธ ๋ฒˆํ˜ธ๋ฅผ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Maven์œผ๋กœ ADK ์›น ์„œ๋ฒ„๋ฅผ ์ปดํŒŒ์ผํ•˜๊ณ  ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

mvn compile exec:java \
 -Dexec.args="--adk.agents.source-dir=src/main/java/agents --server.port=8080"

Gradle์˜ ๊ฒฝ์šฐ, build.gradle ๋˜๋Š” build.gradle.kts ๋นŒ๋“œ ํŒŒ์ผ์˜ ํ”Œ๋Ÿฌ๊ทธ์ธ ์„น์…˜์— ๋‹ค์Œ Java ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

plugins {
    id('java')
    // ๋‹ค๋ฅธ ํ”Œ๋Ÿฌ๊ทธ์ธ๋“ค
}
๊ทธ๋Ÿฐ ๋‹ค์Œ, ๋นŒ๋“œ ํŒŒ์ผ์˜ ๋‹ค๋ฅธ ๊ณณ, ์ตœ์ƒ์œ„ ๋ ˆ๋ฒจ์— ์ƒˆ ํƒœ์Šคํฌ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

tasks.register('runADKWebServer', JavaExec) {
    dependsOn classes
    classpath = sourceSets.main.runtimeClasspath
    mainClass = 'com.google.adk.web.AdkWebServer'
    args '--adk.agents.source-dir=src/main/java/agents', '--server.port=8080'
}

๋งˆ์ง€๋ง‰์œผ๋กœ, ๋ช…๋ น์ค„์—์„œ ๋‹ค์Œ ๋ช…๋ น์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

gradle runADKWebServer

Java์—์„œ๋Š” Dev UI์™€ API ์„œ๋ฒ„๊ฐ€ ํ•จ๊ป˜ ๋ฒˆ๋“ค๋กœ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.

์ด ๋ช…๋ น์–ด๋Š” ๋กœ์ปฌ ์›น ์„œ๋ฒ„๋ฅผ ์‹œ์ž‘ํ•˜๋ฉฐ, ์—ฌ๊ธฐ์„œ cURL ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๊ฑฐ๋‚˜ API ์š”์ฒญ์„ ๋ณด๋‚ด ์—์ด์ „ํŠธ๋ฅผ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ณ ๊ธ‰ ์‚ฌ์šฉ๋ฒ• ๋ฐ ๋””๋ฒ„๊น…

์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ์—”๋“œํฌ์ธํŠธ, ์š”์ฒญ/์‘๋‹ต ํ˜•์‹, ๋””๋ฒ„๊น… ํŒ(๋Œ€ํ™”ํ˜• API ๋ฌธ์„œ ์‚ฌ์šฉ ๋ฐฉ๋ฒ• ํฌํ•จ)์— ๋Œ€ํ•œ ์ „์ฒด ์ฐธ์กฐ๋Š” ์•„๋ž˜ ADK API ์„œ๋ฒ„ ๊ฐ€์ด๋“œ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.

๋กœ์ปฌ ํ…Œ์ŠคํŠธ

๋กœ์ปฌ ํ…Œ์ŠคํŠธ๋Š” ๋กœ์ปฌ ์›น ์„œ๋ฒ„๋ฅผ ์‹œ์ž‘ํ•˜๊ณ , ์„ธ์…˜์„ ์ƒ์„ฑํ•˜๊ณ , ์—์ด์ „ํŠธ์— ์ฟผ๋ฆฌ๋ฅผ ๋ณด๋‚ด๋Š” ๊ณผ์ •์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ๋จผ์ €, ์˜ฌ๋ฐ”๋ฅธ ์ž‘์—… ๋””๋ ‰ํ„ฐ๋ฆฌ์— ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”.

parent_folder/
โ””โ”€โ”€ my_sample_agent/
    โ””โ”€โ”€ agent.py (๋˜๋Š” Agent.java)

๋กœ์ปฌ ์„œ๋ฒ„ ์‹œ์ž‘

๋‹ค์Œ์œผ๋กœ, ์œ„์— ๋‚˜์—ด๋œ ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์—ฌ ๋กœ์ปฌ ์„œ๋ฒ„๋ฅผ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

์ถœ๋ ฅ์€ ๋‹ค์Œ๊ณผ ์œ ์‚ฌํ•˜๊ฒŒ ๋‚˜ํƒ€๋‚˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.

INFO:     Started server process [12345]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://localhost:8000 (Press CTRL+C to quit)
2025-05-13T23:32:08.972-06:00  INFO 37864 --- [ebServer.main()] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port 8080 (http) with context path '/'
2025-05-13T23:32:08.980-06:00  INFO 37864 --- [ebServer.main()] com.google.adk.web.AdkWebServer          : Started AdkWebServer in 1.15 seconds (process running for 2.877)
2025-05-13T23:32:08.981-06:00  INFO 37864 --- [ebServer.main()] com.google.adk.web.AdkWebServer          : AdkWebServer application started successfully.

์ด์ œ ์„œ๋ฒ„๊ฐ€ ๋กœ์ปฌ์—์„œ ์‹คํ–‰ ์ค‘์ž…๋‹ˆ๋‹ค. ์ดํ›„์˜ ๋ชจ๋“  ๋ช…๋ น์–ด์—์„œ ์˜ฌ๋ฐ”๋ฅธ **ํฌํŠธ ๋ฒˆํ˜ธ**๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ƒˆ ์„ธ์…˜ ์ƒ์„ฑ

API ์„œ๋ฒ„๊ฐ€ ๊ณ„์† ์‹คํ–‰ ์ค‘์ธ ์ƒํƒœ์—์„œ ์ƒˆ ํ„ฐ๋ฏธ๋„ ์ฐฝ์ด๋‚˜ ํƒญ์„ ์—ด๊ณ  ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์—ฌ ์—์ด์ „ํŠธ์™€ ์ƒˆ ์„ธ์…˜์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

curl -X POST http://localhost:8000/apps/my_sample_agent/users/u_123/sessions/s_123 \
  -H "Content-Type: application/json" \
  -d '{"key1": "value1", "key2": 42}'

๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๋Š”์ง€ ๋ถ„์„ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

  • http://localhost:8000/apps/my_sample_agent/users/u_123/sessions/s_123: ์ด ์ฃผ์†Œ๋Š” ์—์ด์ „ํŠธ ํด๋” ์ด๋ฆ„์ธ my_sample_agent ์—์ด์ „ํŠธ์— ๋Œ€ํ•ด ์‚ฌ์šฉ์ž ID(u_123)์™€ ์„ธ์…˜ ID(s_123)๋กœ ์ƒˆ ์„ธ์…˜์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. my_sample_agent๋ฅผ ์—ฌ๋Ÿฌ๋ถ„์˜ ์—์ด์ „ํŠธ ํด๋” ์ด๋ฆ„์œผ๋กœ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. u_123์€ ํŠน์ • ์‚ฌ์šฉ์ž ID๋กœ, s_123์€ ํŠน์ • ์„ธ์…˜ ID๋กœ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • {"key1": "value1", "key2": 42}: ์ด ๋ถ€๋ถ„์€ ์„ ํƒ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค. ์„ธ์…˜์„ ์ƒ์„ฑํ•  ๋•Œ ์—์ด์ „ํŠธ์˜ ๊ธฐ์กด ์ƒํƒœ(dict)๋ฅผ ์‚ฌ์šฉ์ž ์ •์˜ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์„ฑ๊ณต์ ์œผ๋กœ ์ƒ์„ฑ๋˜๋ฉด ์„ธ์…˜ ์ •๋ณด๊ฐ€ ๋ฐ˜ํ™˜๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ถœ๋ ฅ์€ ๋‹ค์Œ๊ณผ ์œ ์‚ฌํ•˜๊ฒŒ ๋‚˜ํƒ€๋‚˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.

{"id":"s_123","appName":"my_sample_agent","userId":"u_123","state":{"key1":"value1","key2":42},"events":[],"lastUpdateTime":1743711430.022186}

Info

์ •ํ™•ํžˆ ๋™์ผํ•œ ์‚ฌ์šฉ์ž ID์™€ ์„ธ์…˜ ID๋กœ ์—ฌ๋Ÿฌ ์„ธ์…˜์„ ์ƒ์„ฑํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์‹œ๋„ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์‘๋‹ต์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. {"detail":"Session already exists: s_123"}. ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด ํ•ด๋‹น ์„ธ์…˜(์˜ˆ: s_123)์„ ์‚ญ์ œํ•˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ์„ธ์…˜ ID๋ฅผ ์„ ํƒํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์ฟผ๋ฆฌ ์ „์†ก

POST๋ฅผ ํ†ตํ•ด ์—์ด์ „ํŠธ์— ์ฟผ๋ฆฌ๋ฅผ ๋ณด๋‚ด๋Š” ๋ฐฉ๋ฒ•์—๋Š” /run ๋˜๋Š” /run_sse ๊ฒฝ๋กœ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋‘ ๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  • POST http://localhost:8000/run: ๋ชจ๋“  ์ด๋ฒคํŠธ๋ฅผ ๋ฆฌ์ŠคํŠธ๋กœ ์ˆ˜์ง‘ํ•˜์—ฌ ํ•œ ๋ฒˆ์— ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค (ํ™•์‹คํ•˜์ง€ ์•Š๋‹ค๋ฉด ์ด ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค).
  • POST http://localhost:8000/run_sse: ์„œ๋ฒ„-์ „์†ก ์ด๋ฒคํŠธ(Server-Sent-Events)๋กœ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ, ์ด๋Š” ์ด๋ฒคํŠธ ๊ฐ์ฒด์˜ ์ŠคํŠธ๋ฆผ์ž…๋‹ˆ๋‹ค. ์ด๋ฒคํŠธ๊ฐ€ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ด์ง€๋Š” ์ฆ‰์‹œ ์•Œ๋ฆผ์„ ๋ฐ›๊ณ  ์‹ถ์€ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. /run_sse๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด streaming์„ true๋กœ ์„ค์ •ํ•˜์—ฌ ํ† ํฐ ์ˆ˜์ค€ ์ŠคํŠธ๋ฆฌ๋ฐ์„ ํ™œ์„ฑํ™”ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

/run ์‚ฌ์šฉํ•˜๊ธฐ

curl -X POST http://localhost:8000/run \
-H "Content-Type: application/json" \
-d '{
"app_name": "my_sample_agent",
"user_id": "u_123",
"session_id": "s_123",
"new_message": {
    "role": "user",
    "parts": [{
    "text": "Hey whats the weather in new york today"
    }]
}
}'

/run์„ ์‚ฌ์šฉํ•˜๋ฉด ์ „์ฒด ์ด๋ฒคํŠธ ์ถœ๋ ฅ์ด ๋™์‹œ์— ๋ฆฌ์ŠคํŠธ ํ˜•ํƒœ๋กœ ํ‘œ์‹œ๋˜๋ฉฐ, ๋‹ค์Œ๊ณผ ์œ ์‚ฌํ•˜๊ฒŒ ๋‚˜ํƒ€๋‚˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.

[{"content":{"parts":[{"functionCall":{"id":"af-e75e946d-c02a-4aad-931e-49e4ab859838","args":{"city":"new york"},"name":"get_weather"}}],"role":"model"},"invocationId":"e-71353f1e-aea1-4821-aa4b-46874a766853","author":"weather_time_agent","actions":{"stateDelta":{},"artifactDelta":{},"requestedAuthConfigs":{}},"longRunningToolIds":[],"id":"2Btee6zW","timestamp":1743712220.385936},{"content":{"parts":[{"functionResponse":{"id":"af-e75e946d-c02a-4aad-931e-49e4ab859838","name":"get_weather","response":{"status":"success","report":"The weather in New York is sunny with a temperature of 25 degrees Celsius (41 degrees Fahrenheit)."}}}],"role":"user"},"invocationId":"e-71353f1e-aea1-4821-aa4b-46874a766853","author":"weather_time_agent","actions":{"stateDelta":{},"artifactDelta":{},"requestedAuthConfigs":{}},"id":"PmWibL2m","timestamp":1743712221.895042},{"content":{"parts":[{"text":"OK. The weather in New York is sunny with a temperature of 25 degrees Celsius (41 degrees Fahrenheit).\n"}],"role":"model"},"invocationId":"e-71353f1e-aea1-4821-aa4b-46874a766853","author":"weather_time_agent","actions":{"stateDelta":{},"artifactDelta":{},"requestedAuthConfigs":{}},"id":"sYT42eVC","timestamp":1743712221.899018}]

/run_sse ์‚ฌ์šฉํ•˜๊ธฐ

curl -X POST http://localhost:8000/run_sse \
-H "Content-Type: application/json" \
-d '{
"app_name": "my_sample_agent",
"user_id": "u_123",
"session_id": "s_123",
"new_message": {
    "role": "user",
    "parts": [{
    "text": "Hey whats the weather in new york today"
    }]
},
"streaming": false
}'

streaming์„ true๋กœ ์„ค์ •ํ•˜์—ฌ ํ† ํฐ ์ˆ˜์ค€ ์ŠคํŠธ๋ฆฌ๋ฐ์„ ํ™œ์„ฑํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์‘๋‹ต์ด ์—ฌ๋Ÿฌ ์ฒญํฌ๋กœ ๋ฐ˜ํ™˜๋จ์„ ์˜๋ฏธํ•˜๋ฉฐ, ์ถœ๋ ฅ์€ ๋‹ค์Œ๊ณผ ์œ ์‚ฌํ•˜๊ฒŒ ๋‚˜ํƒ€๋‚˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.

data: {"content":{"parts":[{"functionCall":{"id":"af-f83f8af9-f732-46b6-8cb5-7b5b73bbf13d","args":{"city":"new york"},"name":"get_weather"}}],"role":"model"},"invocationId":"e-3f6d7765-5287-419e-9991-5fffa1a75565","author":"weather_time_agent","actions":{"stateDelta":{},"artifactDelta":{},"requestedAuthConfigs":{}},"longRunningToolIds":[],"id":"ptcjaZBa","timestamp":1743712255.313043}

data: {"content":{"parts":[{"functionResponse":{"id":"af-f83f8af9-f732-46b6-8cb5-7b5b73bbf13d","name":"get_weather","response":{"status":"success","report":"The weather in New York is sunny with a temperature of 25 degrees Celsius (41 degrees Fahrenheit)."}}}],"role":"user"},"invocationId":"e-3f6d7765-5287-419e-9991-5fffa1a75565","author":"weather_time_agent","actions":{"stateDelta":{},"artifactDelta":{},"requestedAuthConfigs":{}},"id":"5aocxjaq","timestamp":1743712257.387306}

data: {"content":{"parts":[{"text":"OK. The weather in New York is sunny with a temperature of 25 degrees Celsius (41 degrees Fahrenheit).\n"}],"role":"model"},"invocationId":"e-3f6d7765-5287-419e-9991-5fffa1a75565","author":"weather_time_agent","actions":{"stateDelta":{},"artifactDelta":{},"requestedAuthConfigs":{}},"id":"rAnWGSiV","timestamp":1743712257.391317}
/run ๋˜๋Š” /run_sse๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ base64๋กœ ์ธ์ฝ”๋”ฉ๋œ ํŒŒ์ผ๊ณผ ํ•จ๊ป˜ ์ฟผ๋ฆฌ ์ „์†ก

curl -X POST http://localhost:8000/run \
--H 'Content-Type: application/json' \
--d '{
   "appName":"my_sample_agent",
   "userId":"u_123",
   "sessionId":"s_123",
   "newMessage":{
      "role":"user",
      "parts":[
         {
            "text":"Describe this image"
         },
         {
            "inlineData":{
               "displayName":"my_image.png",
               "data":"iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAACXBIWXMAAAsTAAALEwEAmpw...",
               "mimeType":"image/png"
            }
         }
      ]
   },
   "streaming":false
}'

Info

/run_sse๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ, ๊ฐ ์ด๋ฒคํŠธ๊ฐ€ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ด์ง€๋Š” ์ฆ‰์‹œ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ†ตํ•ฉ

ADK๋Š” ์ฝœ๋ฐฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ์„œ๋“œํŒŒํ‹ฐ ๊ด€์ธก ๊ฐ€๋Šฅ์„ฑ ๋„๊ตฌ์™€ ํ†ตํ•ฉ๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ํ†ตํ•ฉ์€ ์—์ด์ „ํŠธ ํ˜ธ์ถœ ๋ฐ ์ƒํ˜ธ ์ž‘์šฉ์˜ ์ƒ์„ธํ•œ ์ถ”์ ์„ ์บก์ฒ˜ํ•˜๋ฉฐ, ์ด๋Š” ๋™์ž‘์„ ์ดํ•ดํ•˜๊ณ  ๋ฌธ์ œ๋ฅผ ๋””๋ฒ„๊น…ํ•˜๋ฉฐ ์„ฑ๋Šฅ์„ ํ‰๊ฐ€ํ•˜๋Š” ๋ฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

์—์ด์ „ํŠธ ๋ฐฐํฌํ•˜๊ธฐ

์ด์ œ ์—์ด์ „ํŠธ์˜ ๋กœ์ปฌ ์ž‘๋™์„ ํ™•์ธํ–ˆ์œผ๋ฏ€๋กœ, ์—์ด์ „ํŠธ ๋ฐฐํฌ ๋‹จ๊ณ„๋กœ ๋„˜์–ด๊ฐˆ ์ค€๋น„๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค! ์—์ด์ „ํŠธ๋ฅผ ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ช‡ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • Agent Runtime์— ๋ฐฐํฌํ•˜๊ธฐ: ADK ์—์ด์ „ํŠธ๋ฅผ Google Cloud์˜ ๊ด€๋ฆฌํ˜• Agent Platform ์„œ๋น„์Šค์— ๋ฐฐํฌํ•˜๋Š” ๊ฐ€์žฅ ์‰ฌ์šด ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.
  • Cloud Run์— ๋ฐฐํฌํ•˜๊ธฐ: Google Cloud์˜ ์„œ๋ฒ„๋ฆฌ์Šค ์•„ํ‚คํ…์ฒ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์—์ด์ „ํŠธ๋ฅผ ํ™•์žฅํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์™„์ „ํžˆ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ADK API ์„œ๋ฒ„

ADK API ์„œ๋ฒ„๋Š” ์—์ด์ „ํŠธ๋ฅผ RESTful API๋ฅผ ํ†ตํ•ด ๋…ธ์ถœํ•˜๋Š” ๋ฏธ๋ฆฌ ํŒจํ‚ค์ง•๋œ FastAPI ์›น ์„œ๋ฒ„์ž…๋‹ˆ๋‹ค. ๋กœ์ปฌ ํ…Œ์ŠคํŠธ ๋ฐ ๊ฐœ๋ฐœ์„ ์œ„ํ•œ ์ฃผ์š” ๋„๊ตฌ์ด๋ฉฐ, ๋ฐฐํฌํ•˜๊ธฐ ์ „์— ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹์œผ๋กœ ์—์ด์ „ํŠธ์™€ ์ƒํ˜ธ ์ž‘์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.

์„œ๋ฒ„ ์‹คํ–‰ํ•˜๊ธฐ

์„œ๋ฒ„๋ฅผ ์‹œ์ž‘ํ•˜๋ ค๋ฉด ํ”„๋กœ์ ํŠธ์˜ ๋ฃจํŠธ ๋””๋ ‰ํ„ฐ๋ฆฌ์—์„œ ๋‹ค์Œ ๋ช…๋ น์„ ์‹คํ–‰ํ•˜์„ธ์š”.

adk api_server

๊ธฐ๋ณธ์ ์œผ๋กœ ์„œ๋ฒ„๋Š” http://localhost:8000์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ์„œ๋ฒ„๊ฐ€ ์‹œ์ž‘๋˜์—ˆ์Œ์„ ํ™•์ธํ•˜๋Š” ์ถœ๋ ฅ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

INFO:     Uvicorn running on http://localhost:8000 (Press CTRL+C to quit)

๋Œ€ํ™”ํ˜• API ๋ฌธ์„œ๋กœ ๋””๋ฒ„๊น…ํ•˜๊ธฐ

API ์„œ๋ฒ„๋Š” Swagger UI๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋Œ€ํ™”ํ˜• API ๋ฌธ์„œ๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์—”๋“œํฌ์ธํŠธ๋ฅผ ํƒ์ƒ‰ํ•˜๊ณ , ์š”์ฒญ ํ˜•์‹์„ ์ดํ•ดํ•˜๋ฉฐ, ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ง์ ‘ ์—์ด์ „ํŠธ๋ฅผ ํ…Œ์ŠคํŠธํ•˜๋Š” ๋ฐ ๋งค์šฐ ์œ ์šฉํ•œ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค.

๋Œ€ํ™”ํ˜• ๋ฌธ์„œ์— ์•ก์„ธ์Šคํ•˜๋ ค๋ฉด API ์„œ๋ฒ„๋ฅผ ์‹œ์ž‘ํ•˜๊ณ  ์›น ๋ธŒ๋ผ์šฐ์ €์—์„œ http://localhost:8000/docs๋กœ ์ด๋™ํ•˜์„ธ์š”.

์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  API ์—”๋“œํฌ์ธํŠธ์˜ ์™„์ „ํ•˜๊ณ  ๋Œ€ํ™”ํ˜•์ธ ๋ชฉ๋ก์ด ํ‘œ์‹œ๋˜๋ฉฐ, ์ด๋ฅผ ํ™•์žฅํ•˜์—ฌ ํŒŒ๋ผ๋ฏธํ„ฐ, ์š”์ฒญ ๋ณธ๋ฌธ ๋ฐ ์‘๋‹ต ์Šคํ‚ค๋งˆ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ์ •๋ณด๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. "Try it out"์„ ํด๋ฆญํ•˜์—ฌ ์‹คํ–‰ ์ค‘์ธ ์—์ด์ „ํŠธ์— ์‹ค์‹œ๊ฐ„ ์š”์ฒญ์„ ๋ณด๋‚ผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

API ์—”๋“œํฌ์ธํŠธ

๋‹ค์Œ ์„น์…˜์—์„œ๋Š” ์—์ด์ „ํŠธ์™€ ์ƒํ˜ธ ์ž‘์šฉํ•˜๊ธฐ ์œ„ํ•œ ์ฃผ์š” ์—”๋“œํฌ์ธํŠธ์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

JSON ์ด๋ฆ„ ๊ทœ์น™

  • ์š”์ฒญ ๋ณธ๋ฌธ์€ ํ•„๋“œ ์ด๋ฆ„์— snake_case๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค (์˜ˆ: "app_name").
  • ์‘๋‹ต ๋ณธ๋ฌธ์€ ํ•„๋“œ ์ด๋ฆ„์— camelCase๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค (์˜ˆ: "appName").

์œ ํ‹ธ๋ฆฌํ‹ฐ ์—”๋“œํฌ์ธํŠธ

์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์—์ด์ „ํŠธ ๋ชฉ๋ก ์กฐํšŒ

์„œ๋ฒ„์—์„œ ๋ฐœ๊ฒฌํ•œ ๋ชจ๋“  ์—์ด์ „ํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ชฉ๋ก์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

  • ๋ฉ”์„œ๋“œ: GET
  • ๊ฒฝ๋กœ: /list-apps

์š”์ฒญ ์˜ˆ์‹œ

curl -X GET http://localhost:8000/list-apps

์‘๋‹ต ์˜ˆ์‹œ

["my_sample_agent", "another_agent"]


์„ธ์…˜ ๊ด€๋ฆฌ

์„ธ์…˜์€ ํŠน์ • ์‚ฌ์šฉ์ž๊ฐ€ ์—์ด์ „ํŠธ์™€ ์ƒํ˜ธ ์ž‘์šฉํ•˜๋Š” ๋™์•ˆ์˜ ์ƒํƒœ์™€ ์ด๋ฒคํŠธ ๊ธฐ๋ก์„ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

์„ธ์…˜ ์ƒ์„ฑ ๋˜๋Š” ์—…๋ฐ์ดํŠธ

์ƒˆ ์„ธ์…˜์„ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ๊ธฐ์กด ์„ธ์…˜์„ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค. ์ง€์ •๋œ ID๋ฅผ ๊ฐ€์ง„ ์„ธ์…˜์ด ์ด๋ฏธ ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ, ํ•ด๋‹น ์ƒํƒœ๋Š” ์ œ๊ณต๋œ ์ƒˆ ์ƒํƒœ๋กœ ๋ฎ์–ด์“ฐ์—ฌ์ง‘๋‹ˆ๋‹ค.

  • ๋ฉ”์„œ๋“œ: POST
  • ๊ฒฝ๋กœ: /apps/{app_name}/users/{user_id}/sessions/{session_id}

์š”์ฒญ ๋ณธ๋ฌธ

{
  "key1": "value1",
  "key2": 42
}

์š”์ฒญ ์˜ˆ์‹œ

curl -X POST http://localhost:8000/apps/my_sample_agent/users/u_123/sessions/s_abc \
  -H "Content-Type: application/json" \
  -d '{"visit_count": 5}'

์‘๋‹ต ์˜ˆ์‹œ

{"id":"s_abc","appName":"my_sample_agent","userId":"u_123","state":{"visit_count":5},"events":[],"lastUpdateTime":1743711430.022186}

์„ธ์…˜ ์กฐํšŒ

ํŠน์ • ์„ธ์…˜์˜ ์„ธ๋ถ€ ์ •๋ณด(ํ˜„์žฌ ์ƒํƒœ ๋ฐ ๋ชจ๋“  ๊ด€๋ จ ์ด๋ฒคํŠธ ํฌํ•จ)๋ฅผ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค.

  • ๋ฉ”์„œ๋“œ: GET
  • ๊ฒฝ๋กœ: /apps/{app_name}/users/{user_id}/sessions/{session_id}

์š”์ฒญ ์˜ˆ์‹œ

curl -X GET http://localhost:8000/apps/my_sample_agent/users/u_123/sessions/s_abc

์‘๋‹ต ์˜ˆ์‹œ

{"id":"s_abc","appName":"my_sample_agent","userId":"u_123","state":{"visit_count":5},"events":[...],"lastUpdateTime":1743711430.022186}

์„ธ์…˜ ์‚ญ์ œ

์„ธ์…˜ ๋ฐ ๋ชจ๋“  ๊ด€๋ จ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.

  • ๋ฉ”์„œ๋“œ: DELETE
  • ๊ฒฝ๋กœ: /apps/{app_name}/users/{user_id}/sessions/{session_id}

์š”์ฒญ ์˜ˆ์‹œ

curl -X DELETE http://localhost:8000/apps/my_sample_agent/users/u_123/sessions/s_abc

์‘๋‹ต ์˜ˆ์‹œ ์„ฑ๊ณต์ ์œผ๋กœ ์‚ญ์ œ๋˜๋ฉด 204 No Content ์ƒํƒœ ์ฝ”๋“œ์™€ ํ•จ๊ป˜ ๋นˆ ์‘๋‹ต์ด ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.


์—์ด์ „ํŠธ ์‹คํ–‰

์ด ์—”๋“œํฌ์ธํŠธ๋“ค์€ ์—์ด์ „ํŠธ์— ์ƒˆ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๊ณ  ์‘๋‹ต์„ ๋ฐ›๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

์—์ด์ „ํŠธ ์‹คํ–‰ (๋‹จ์ผ ์‘๋‹ต)

์—์ด์ „ํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์‹คํ–‰์ด ์™„๋ฃŒ๋œ ํ›„ ์ƒ์„ฑ๋œ ๋ชจ๋“  ์ด๋ฒคํŠธ๋ฅผ ๋‹จ์ผ JSON ๋ฐฐ์—ด๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

  • ๋ฉ”์„œ๋“œ: POST
  • ๊ฒฝ๋กœ: /run

์š”์ฒญ ๋ณธ๋ฌธ

{
  "app_name": "my_sample_agent",
  "user_id": "u_123",
  "session_id": "s_abc",
  "new_message": {
    "role": "user",
    "parts": [
      { "text": "What is the capital of France?" }
    ]
  }
}

์š”์ฒญ ์˜ˆ์‹œ

curl -X POST http://localhost:8000/run \
  -H "Content-Type: application/json" \
  -d '{
    "app_name": "my_sample_agent",
    "user_id": "u_123",
    "session_id": "s_abc",
    "new_message": {
      "role": "user",
      "parts": [{"text": "What is the capital of France?"}]
    }
  }'

์—์ด์ „ํŠธ ์‹คํ–‰ (์ŠคํŠธ๋ฆฌ๋ฐ)

์—์ด์ „ํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์ด๋ฒคํŠธ๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ๋งˆ๋‹ค ์„œ๋ฒ„-์ „์†ก ์ด๋ฒคํŠธ(SSE)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ๋กœ ์ŠคํŠธ๋ฆฌ๋ฐํ•ฉ๋‹ˆ๋‹ค.

  • ๋ฉ”์„œ๋“œ: POST
  • ๊ฒฝ๋กœ: /run_sse

์š”์ฒญ ๋ณธ๋ฌธ ์š”์ฒญ ๋ณธ๋ฌธ์€ /run๊ณผ ๋™์ผํ•˜๋ฉฐ, ์„ ํƒ์  streaming ํ”Œ๋ž˜๊ทธ๊ฐ€ ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค.

{
  "app_name": "my_sample_agent",
  "user_id": "u_123",
  "session_id": "s_abc",
  "new_message": {
    "role": "user",
    "parts": [
      { "text": "What is the weather in New York?" }
    ]
  },
  "streaming": true
}
- streaming: (์„ ํƒ ์‚ฌํ•ญ) true๋กœ ์„ค์ •ํ•˜๋ฉด ๋ชจ๋ธ ์‘๋‹ต์— ๋Œ€ํ•ด ํ† ํฐ ์ˆ˜์ค€ ์ŠคํŠธ๋ฆฌ๋ฐ์„ ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ false์ž…๋‹ˆ๋‹ค.

์š”์ฒญ ์˜ˆ์‹œ

curl -X POST http://localhost:8000/run_sse \
  -H "Content-Type: application/json" \
  -d '{
    "app_name": "my_sample_agent",
    "user_id": "u_123",
    "session_id": "s_abc",
    "new_message": {
      "role": "user",
      "parts": [{"text": "What is the weather in New York?"}]
    },
    "streaming": false
  }'