에이전트를 만들려면 샌드박스를 프로비저닝하고, 도구를 연결하고, 실행 루프를 유지해야 했습니다. 2026년 5월 19일부터는 아닙니다. Gemini API Managed Agents는 client.interactions.create() 한 줄로 격리 Linux 환경을 띄우고, Gemini 3.5 Flash 에이전트가 코드 실행·웹 검색·파일 관리를 자율적으로 처리합니다. 설치부터 커스텀 에이전트 등록, 스트리밍, 백그라운드 실행까지 실제 코드로 전부 정리했습니다.
이 포스트 한 줄 요약 → 에이전트 ID: antigravity-preview-05-2026 (Gemini 3.5 Flash 기반, 퍼블릭 프리뷰) → SDK: google-genai >= 2.0.0 필수 — 기존 google-generativeai deprecated → 샌드박스 기본 도구: Bash/Python/Node.js 실행, 파일 관리, Google Search, URL 패치 → 멀티턴: previous_interaction_id로 세션·파일 상태 유지 → 스트리밍: stream=True, 백그라운드 장기 태스크: background=True + 폴링 → AGENTS.md + SKILL.md로 오케스트레이션 코드 없이 에이전트 커스터마이즈 → ⚠️ Breaking change: 5월 26일부로 outputs → steps 배열 전환, 6월 8일 레거시 스키마 완전 제거 → 인터랙션 저장: 유료 55일, 무료 1일 (기본 store=True) → 컨텍스트 자동 압축: ~135K 토큰에서 자동 실행
0단계: 설치 및 환경 준비
# 기존 google-generativeai가 있다면 제거
pip uninstall google-generativeai -y
# 반드시 2.0.0 이상
pip install -U google-genai
# API 키 설정
export GEMINI_API_KEY="your-api-key-here"
from google import genai
client = genai.Client()
# 별도 설정 없이 GEMINI_API_KEY 환경변수 자동 인식
1단계: 첫 번째 호출 — 기본 에이전트 실행
from google import genai
client = genai.Client()
# 단일 호출 → 격리 Linux 샌드박스 프로비저닝 + 에이전트 루프 자동 실행
interaction = client.interactions.create(
agent="antigravity-preview-05-2026",
input="Hacker News 상위 10개 기사를 읽고 요약해서 PDF로 저장해줘.",
environment={"type": "remote"}, # 새 샌드박스 생성
)
# steps 배열에서 최종 텍스트 출력 (5/26 이후 새 스키마)
print(interaction.steps[-1].content[0].text)
⚠️ 주의: 5월 26일부로 응답 스키마가 바뀌었습니다. 기존에 interaction.outputs를 쓰던 코드는 interaction.steps로 교체해야 합니다. 6월 8일 이후 레거시 스키마는 완전히 제거됩니다.
curl로 직접 호출
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "Api-Revision: 2026-05-20" \
-d '{
"agent": "antigravity-preview-05-2026",
"input": "피보나치 수열 20개를 계산하고 fibonacci.txt에 저장해줘.",
"environment": "remote"
}'
2단계: 스트리밍 — 실시간 진행 상황 확인
긴 작업에서 완료까지 기다리지 않고 에이전트의 각 단계를 실시간으로 받을 수 있습니다.
stream = client.interactions.create(
agent="antigravity-preview-05-2026",
input="sales_data.csv를 분석하고 월별 매출 차트를 포함한 리포트를 만들어줘.",
environment={"type": "remote"},
stream=True,
)
for event in stream:
if event.event_type == "step.start":
print(f"\n▶ 단계 시작: {event.step.type}")
elif event.event_type == "step.delta":
if event.delta.type == "text":
print(event.delta.text, end="", flush=True)
elif event.delta.type == "thought_summary":
# 에이전트 내부 추론 과정 (선택적 표시)
print(f"\n[추론] {event.delta.content.text}")
elif event.event_type == "interaction.completed":
usage = event.interaction.usage
print(f"\n\n✅ 완료 — 총 토큰: {usage.total_tokens:,}")
출력 예시:
▶ 단계 시작: code_execution
[추론] CSV 파일을 pandas로 읽어 월별 집계를 계산합니다.
▶ 단계 시작: file_management
리포트 파일을 저장합니다.
✅ 완료 — 총 토큰: 18,432
3단계: 멀티턴 세션 — 상태와 파일 이어받기
previous_interaction_id로 이전 인터랙션의 샌드박스 상태(파일, 변수, 실행 결과)를 그대로 유지합니다.
# 1턴: 데이터 로드 및 기본 분석
interaction_1 = client.interactions.create(
agent="antigravity-preview-05-2026",
input="q1_sales.csv를 불러와서 지역별 매출 합계를 계산해줘.",
environment={"type": "remote"},
)
print("1턴 완료:", interaction_1.steps[-1].content[0].text)
# 2턴: 이전 환경 이어받기 (파일·변수 유지)
interaction_2 = client.interactions.create(
agent="antigravity-preview-05-2026",
input="방금 계산한 지역별 합계를 막대그래프로 시각화하고 PNG로 저장해줘.",
environment={
"type": "remote",
"previous_interaction_id": interaction_1.id, # 이전 환경 재사용
},
)
# 3턴: 최종 리포트 생성
interaction_3 = client.interactions.create(
agent="antigravity-preview-05-2026",
input="차트와 수치를 합쳐서 PDF 리포트로 만들어줘. 파일명은 q1_report.pdf로.",
environment={
"type": "remote",
"previous_interaction_id": interaction_2.id,
},
)
4단계: 생성된 파일 다운로드
에이전트가 샌드박스 안에서 만든 파일을 로컬로 가져옵니다.
import os
interaction = client.interactions.create(
agent="antigravity-preview-05-2026",
input="소수 50개를 계산하고 분포 차트를 primes_report.pdf로 저장해줘.",
environment={"type": "remote"},
)
# 샌드박스에서 생성된 파일 목록 확인
for file in interaction.files:
print(f"파일: {file.name} ({file.size:,} bytes)")
# 특정 파일 다운로드
output_dir = "./agent_output"
os.makedirs(output_dir, exist_ok=True)
for file in interaction.files:
if file.name.endswith(".pdf"):
local_path = os.path.join(output_dir, file.name)
with open(local_path, "wb") as f:
f.write(file.content)
print(f"✅ 저장됨: {local_path}")
5단계: AGENTS.md + SKILL.md로 커스터마이즈
오케스트레이션 코드 대신 마크다운 파일로 에이전트 행동을 정의합니다.
interaction = client.interactions.create(
agent="antigravity-preview-05-2026",
input="이번 달 KPI 리포트를 만들어줘.",
system_instruction="너는 데이터 분석 전문 에이전트야. 항상 수치 근거를 포함해.",
environment={
"type": "remote",
"sources": [
# AGENTS.md: 프로젝트 전체 컨벤션
{
"type": "inline",
"target": ".agents/AGENTS.md",
"content": """
# 분석 에이전트 지침
- 모든 차트는 matplotlib 사용, 한글 폰트 적용
- 리포트에 항상 요약 테이블(markdown) 포함
- 숫자는 천 단위 콤마 적용 (예: 1,234,567)
- 결론은 bullet point 3개로 요약
- 출력 파일은 항상 /workspace/output/ 디렉토리에 저장
""".strip(),
},
# SKILL.md: 특정 기능 정의
{
"type": "inline",
"target": ".agents/skills/pdf-report/SKILL.md",
"content": """
---
name: pdf-report
description: 데이터 분석 결과를 PDF 슬라이드로 변환합니다.
---
# PDF Report Skill
## 사용 조건
리포트 생성 요청 시 자동 호출됩니다.
## 실행 방법
1. matplotlib으로 차트 생성
2. pandas DataFrame을 HTML 테이블로 변환
3. reportlab으로 PDF 합성
4. /workspace/output/{파일명}.pdf로 저장
""".strip(),
},
# GitHub에서 공유 스킬 라이브러리 마운트
{
"type": "repository",
"source": "https://github.com/your-org/agent-skills",
"target": ".agents/skills/shared",
},
],
},
)
6단계: 에이전트 등록 — ID로 재사용
매번 인라인으로 정의하는 대신 에이전트를 한 번 등록해두고 ID로 호출합니다. 프로덕션 환경에서 일관된 동작을 보장하는 핵심 패턴입니다.
# 에이전트 등록 (한 번만)
agent = client.agents.create(
id="kpi-analyst-v1", # 고유 ID
base_agent="antigravity-preview-05-2026",
system_instruction=(
"KPI 분석 전문 에이전트. "
"항상 차트와 요약 테이블을 포함하고 PDF로 저장한다."
),
base_environment={
"type": "remote",
"sources": [
{
"type": "inline",
"target": ".agents/AGENTS.md",
"content": "항상 matplotlib 사용. 한글 지원 폰트 적용 필수.",
},
{
"type": "repository",
"source": "https://github.com/your-org/agent-skills",
"target": ".agents/skills",
},
],
},
)
print(f"등록된 에이전트 ID: {agent.id}")
# 이후 ID 하나로 호출
interaction = client.interactions.create(
agent="kpi-analyst-v1", # 등록된 에이전트 ID
input="3월 매출 데이터 분석해줘.",
)
7단계: 백그라운드 모드 — 장기 태스크 처리
Deep Research처럼 수 분이 걸리는 작업에는 background=True로 비동기 실행 후 폴링합니다.
import time
# 백그라운드로 시작
initial = client.interactions.create(
agent="deep-research-preview-04-2026",
input="2026년 AI 에이전트 시장 동향을 분석하고 20페이지 분량의 리포트를 작성해줘.",
background=True,
)
print(f"태스크 시작됨 (ID: {initial.id})")
# 완료까지 폴링
while True:
interaction = client.interactions.get(initial.id)
if interaction.status == "completed":
print("✅ 완료")
print(interaction.steps[-1].content[0].text)
break
elif interaction.status in ("failed", "cancelled"):
print(f"❌ 실패: {interaction.status}")
break
else:
print(f"⏳ 진행 중... (상태: {interaction.status})")
time.sleep(10) # 10초마다 확인
실무 패턴 — 자주 쓰는 시나리오 3가지
① CSV → 분석 리포트 파이프라인
import base64
# 로컬 파일을 에이전트 샌드박스에 업로드
with open("sales_data.csv", "rb") as f:
csv_content = base64.b64encode(f.read()).decode()
interaction = client.interactions.create(
agent="kpi-analyst-v1",
input="업로드된 sales_data.csv를 분석하고 q1_report.pdf를 만들어줘.",
environment={
"type": "remote",
"sources": [
{
"type": "inline",
"target": "workspace/sales_data.csv",
"content": csv_content,
"encoding": "base64",
}
],
},
)
# 결과 PDF 다운로드
for file in interaction.files:
if file.name == "q1_report.pdf":
with open("q1_report.pdf", "wb") as f:
f.write(file.content)
② 웹 스크래핑 + 정형화 파이프라인
interaction = client.interactions.create(
agent="antigravity-preview-05-2026",
input="""
다음 3개 URL에서 가격 정보를 수집하고 비교표를 JSON으로 저장해줘:
- https://example.com/product/a
- https://example.com/product/b
- https://example.com/product/c
""",
environment={"type": "remote"},
)
# 에이전트가 실제로 URL을 패치하고 파싱한 결과 반환
print(interaction.steps[-1].content[0].text)
③ 코드 실행 결과 검증
interaction = client.interactions.create(
agent="antigravity-preview-05-2026",
input="""
다음 Python 함수를 테스트해줘:
def fibonacci(n):
if n <= 1: return n
return fibonacci(n-1) + fibonacci(n-2)
1) 정확성 테스트 (n=0~10 전체 케이스)
2) 성능 측정 (n=30, 35 실행 시간)
3) 개선된 메모이제이션 버전 작성 후 성능 비교
""",
environment={"type": "remote"},
)
주의해야 할 세 가지
① 6월 8일 레거시 스키마 완전 제거
# ❌ 레거시 (6월 8일 이후 에러 발생)
result = interaction.outputs[0].text
# ✅ 새 스키마 (지금 바로 전환)
result = interaction.steps[-1].content[0].text
② store=False는 세션 재개 불가
인터랙션 저장을 끄면 previous_interaction_id 사용이 불가능합니다. 멀티턴 세션이 필요하다면 반드시 store=True(기본값) 상태를 유지해야 합니다.
# store=False 사용 시: 비용 절감 가능하지만 세션 재개 불가
interaction = client.interactions.create(
agent="antigravity-preview-05-2026",
input="단순 일회성 태스크",
environment={"type": "remote"},
store=False, # 저장 안 함 → previous_interaction_id 사용 불가
)
③ 컨텍스트 자동 압축 인지
롱 세션에서 약 135K 토큰에 도달하면 자동으로 컨텍스트 압축이 실행됩니다. 이 과정에서 초반 세션의 세밀한 내용이 요약될 수 있습니다. 장기 프로젝트라면 중요한 중간 결과물을 파일로 명시적으로 저장하도록 에이전트에 지시하는 것이 안전합니다.
✅ 결론
항목 평가
| 시작 난이도 | ✅ API 호출 5줄로 에이전트 실행 가능 |
| 인프라 관리 | ✅ 샌드박스·루프 전부 플랫폼 처리 |
| 멀티턴 상태 관리 | ✅ previous_interaction_id로 간단히 |
| 커스터마이즈 방식 | ✅ 마크다운 파일로 선언적 정의 |
| 스트리밍·백그라운드 | ✅ 두 모드 모두 지원 |
| Breaking change 위험 | ⚠️ 6월 8일 스키마 전환 대응 필수 |
| 현재 성숙도 | ⚠️ 퍼블릭 프리뷰, 프로덕션 안정성 검증 필요 |
Gemini API Managed Agents는 "에이전트를 만들기 위한 인프라"를 학습하는 시간을 줄이고, "에이전트가 실제로 무엇을 해야 하는가"에 집중할 수 있게 해주는 방향입니다. AGENTS.md 컨벤션이 Grok Build, Antigravity, Claude Code 전반에서 수렴되고 있다는 점도 주목할 만합니다 — 에이전트 행동을 코드가 아닌 마크다운으로 정의하는 방식이 표준이 되고 있습니다.
관련 포스트
https://cell-devlog.tistory.com/256
에이전트 코드 다 짤 필요 없습니다 — Managed Agents vs 직접 오케스트레이션 실전 비교
에이전트를 만들려면 LangGraph 그래프를 설계하고, 샌드박스를 프로비저닝하고, 에이전트 루프를 유지하고, 상태를 관리해야 한다 — 2026년 5월 18일까지는 맞는 말이었습니다. 5월 19일 Google I/O에
cell-devlog.tistory.com
'Gemini' 카테고리의 다른 글
| 텍스트·이미지·오디오로 영상을 만든다 — Gemini Omni 완전 분석 (0) | 2026.05.27 |
|---|---|
| Flash가 Pro를 이겼다는 게 정말 맞나 — 벤치마크 신뢰성 5가지 논점 (0) | 2026.05.26 |
| 에이전트 코드 다 짤 필요 없습니다 — Managed Agents vs 직접 오케스트레이션 실전 비교 (0) | 2026.05.26 |
| Flash가 Pro를 이겼다 — Gemini 3.5 Flash 완전 분석 (2026) (0) | 2026.05.26 |
| Gemini Managed Agents API 완전 가이드 — 단일 API 호출로 격리된 Linux 환경에서 에이전트 실행하기 (0) | 2026.05.20 |