Notes
12분 읽기Tech

Spring AI로 Pi 스타일 코딩 에이전트 만들기

Pi Agent Harness의 핵심 아이디어를 Java/Spring 생태계에 맞게 재해석해, Spring AI 2.0 기반의 안전한 코딩 에이전트 런타임으로 구현할 수 있는지 검토한 노트.

Spring AI로 Pi 스타일 코딩 에이전트 만들기

한 줄 요약

Pi를 Spring AI로 1:1 포팅하기보다, Pi의 agent runtime, tool loop, session tree, safety policy를 Java/Spring 방식으로 재해석한 Pi-inspired Spring AI Coding Agent Harness로 만드는 편이 현실적이다.

먼저 읽을 결론

가능하다. 다만 핵심 과제는 Spring AI로 LLM을 호출하는 것이 아니라, 상태를 가진 tool-use runtime을 설계하는 일이다.

Spring AI는 ChatClient, Tool Calling, MCP, Vector Store, Advisor, Observability 같은 기반을 제공한다. 하지만 Pi 수준의 세션 트리, 이벤트 루프, 도구 실행 정책, workspace trust, command sandbox, compaction, evaluation은 직접 설계해야 한다.

추천 방향은 다음과 같다.

판단 항목결론
구현 가능성가능하다. Spring AI 2.0.x가 Spring Boot 4.0.x/4.1.x 계열을 지원하고, tool calling과 MCP 기반을 제공한다.
난이도중상. 단순 챗봇이 아니라 AgentRuntime과 안전한 도구 실행 경계를 만드는 작업이다.
추천 스택Java 21 LTS, Spring Boot 4.1.x, Spring AI 2.0.0, WebFlux/SSE, PostgreSQL + pgvector, Micrometer/OpenTelemetry.
MVP 범위ChatClient + @Tool + ToolCallingAdvisor로 read-only 도구부터 시작한다.
포트폴리오 범위직접 AgentRuntime, ToolPolicyEngine, JSONL session tree, MCP client/server, eval/observability를 구현한다.
차별화 포인트"Java/Spring 백엔드 개발자가 이해하고 운영할 수 있는 안전한 코딩 에이전트 런타임"으로 포지셔닝한다.

왜 저장했나

Spring/Java 백엔드 개발자 관점에서 AI agent를 공부하려면, 모델 API 사용법보다 도구 호출을 안전하게 운영하는 런타임 설계가 더 오래 남는다.

이 노트는 Pi Agent Harness를 참고해 Spring AI 기반 포트폴리오 프로젝트를 설계할 때 다시 볼 수 있는 기준점이다. 특히 다음 질문에 답한다.

  • Pi에서 가져올 핵심 아이디어는 무엇인가?
  • Spring AI가 제공하는 것과 직접 만들어야 하는 것은 무엇인가?
  • 최신 Spring AI 2.0 계열에서 어떤 라이브러리 조합이 적절한가?
  • 학습과 포트폴리오 산출물을 어떤 순서로 쌓을 것인가?
  • 최근 agent 논문과 도구 생태계 논의에서 무엇을 반영할 것인가?

정리한 질문

Pi Agent Harness를 Spring AI 2.0과 Java/Spring 생태계에 맞게 재해석해 구현할 수 있는가? 가능하다면 최신 호환 스택, 아키텍처, 학습 로드맵, 포트폴리오 데모, 관련 논문과 도구 생태계 흐름을 어떻게 정리해야 하는가?

Pi에서 가져올 핵심

Pi는 단순 CLI 챗봇이 아니라 agent harness에 가깝다. 공개 README 기준으로 Pi는 크게 다음 패키지로 나뉜다.

Pi 패키지역할
@earendil-works/pi-aiOpenAI, Anthropic, Google 등 여러 LLM provider를 다루는 unified multi-provider LLM API
@earendil-works/pi-agent-coretool calling과 state management를 담당하는 agent runtime
@earendil-works/pi-coding-agentinteractive coding agent CLI
@earendil-works/pi-tuiterminal UI library

Spring AI 버전에서도 이 구분을 유지하는 편이 좋다.

pi-spring-ai/
  pi-agent-core-spring/
  pi-agent-model-spring/
  pi-agent-tools/
  pi-agent-session/
  pi-agent-mcp/
  pi-agent-api/
  pi-agent-cli/
  pi-agent-eval/

핵심 루프는 다음 형태다.

user prompt
  -> assistant message stream
  -> tool call 생성
  -> tool 실행
  -> tool result 저장
  -> 다음 assistant turn
  -> 필요 시 반복

따라서 구현 대상은 LLM 호출 래퍼가 아니라 AgentRuntime이다.

Spring AI로 가능한 이유

Spring AI는 Java/Spring 개발자가 익숙한 방식으로 AI model, data, API, tool을 연결하기 위한 추상화를 제공한다. 특히 이 프로젝트에 직접 연결되는 부분은 다음이다.

  • ChatClientChatModel
  • @Tool, ToolCallback, ToolCallingAdvisor
  • Advisor 기반 확장
  • Vector Store와 RAG
  • MCP client/server starter
  • Observability와 metrics/tracing
  • LLM-as-Judge evaluation

Spring AI 문서 기준으로 ChatModel을 직접 호출하면 tool definition은 모델에 전달되지만, tool call 실행은 자동으로 처리되지 않는다. 자동 처리가 필요하면 ChatClientToolCallingAdvisor를 쓰거나, 직접 tool execution loop를 구현해야 한다.

그래서 프로젝트는 두 단계로 나누는 편이 좋다.

  1. MVP: ChatClient + @Tool + ToolCallingAdvisor로 작동하는 작은 도구 agent를 만든다.
  2. 포트폴리오: Pi처럼 직접 AgentRuntime, event stream, session tree, tool policy, compaction, eval을 만든다.

최신 호환 스택

2026-06-26 기준으로 실전 포트폴리오에 적합한 기본 조합은 다음이다.

영역추천
JavaJava 21 LTS
FrameworkSpring Boot 4.1.x
AI FrameworkSpring AI 2.0.0
APISpring WebFlux, SSE
CLIpicocli 또는 Spring Shell
PersistencePostgreSQL + pgvector
ObservabilitySpring Boot Actuator + Micrometer + OpenTelemetry
SandboxDocker, Testcontainers, 제한된 working directory
BuildGradle Kotlin DSL 또는 Maven
TestJUnit 5, AssertJ, Testcontainers, WireMock, fake LLM provider

공식 문서상 Spring AI 2.0.x는 Spring Boot 4.0.x와 4.1.x를 지원한다. Spring Boot 4.1.0은 Java 17 이상을 요구하고 Java 26까지 호환된다고 설명한다. 다만 Spring AI 2.0.0 starter가 Spring Boot 4.1.0 계열 dependency를 끌어오는 이슈가 보고된 적이 있으므로, 새 프로젝트라면 Boot 4.1.x에 맞추는 편이 충돌 가능성이 낮다.

Gradle 예시는 다음과 같이 잡을 수 있다.

dependencies {
    implementation(platform("org.springframework.ai:spring-ai-bom:2.0.0"))

    implementation("org.springframework.boot:spring-boot-starter-webflux")
    implementation("org.springframework.boot:spring-boot-starter-actuator")

    implementation("org.springframework.ai:spring-ai-starter-model-openai")
    implementation("org.springframework.ai:spring-ai-starter-model-anthropic")
    implementation("org.springframework.ai:spring-ai-starter-model-ollama")

    implementation("org.springframework.ai:spring-ai-starter-tool-search-advisor")
    implementation("org.springframework.ai:spring-ai-starter-vector-store-pgvector")

    implementation("org.springframework.ai:spring-ai-starter-mcp-client-webflux")
    implementation("org.springframework.ai:spring-ai-starter-mcp-server-webflux")

    testImplementation("org.springframework.boot:spring-boot-starter-test")
    testImplementation("org.testcontainers:junit-jupiter")
    testImplementation("org.testcontainers:postgresql")
}

처음부터 모든 provider를 넣을 필요는 없다. 포트폴리오 기준으로는 OpenAI 또는 Anthropic 하나, Ollama 하나를 먼저 붙이고 ModelRegistry로 provider 교체 구조를 보여주는 편이 낫다.

Pi 기능과 Spring 구현 매핑

Pi 개념Spring AI/Spring 구현
pi-ai multi-providerSpring AI ChatModel, ChatClient, provider별 starter
AgentMessageJava sealed interface 또는 record 기반 message model
transformContext()ContextTransformer, compaction, RAG injection
convertToLlm()LlmMessageMapper
Tool Calling@Tool, ToolCallback, ToolCallingAdvisor
Tool policy hookBeforeToolCallPolicy, AfterToolCallPolicy 직접 구현
Streaming eventsWebFlux Flux<AgentEvent>, SSE
Session JSONLPostgreSQL 또는 파일 기반 JSONL session store
Branching/forkparentId 기반 session tree
SkillsMarkdown 기반 capability loader
ExtensionsSpring bean/plugin 또는 Java SPI
MCPSpring AI MCP client/server starter
TUI우선 Web UI 또는 CLI, 이후 Lanterna/JLine/picocli
SandboxDocker/Testcontainers/제한된 working directory

Pi는 project trust 개념도 가진다. Spring 버전에서는 이를 WorkspaceTrustPolicy로 재해석해, 로컬 설정·extension·도구 실행 전에 workspace 신뢰 여부와 실행 권한을 통제하는 구조로 만들면 좋다.

권장 아키텍처

Core Runtime

AgentRuntime
  ├─ AgentState
  ├─ AgentMessageStore
  ├─ ContextTransformer
  ├─ LlmMessageMapper
  ├─ ModelRouter
  ├─ ToolRegistry
  ├─ ToolExecutionService
  ├─ ToolPolicyEngine
  ├─ AgentEventPublisher
  └─ SessionStore

실행 흐름은 다음처럼 잡는다.

prompt(userInput)
  1. user message 저장
  2. context transform
  3. LLM message 변환
  4. ChatClient/ChatModel 호출
  5. assistant stream event 발행
  6. tool call 감지
  7. beforeToolCall policy 검사
  8. tool 실행
  9. afterToolCall 후처리
  10. tool result message 저장
  11. stop 조건이 아니면 다음 turn

Tool 설계

MVP 도구는 Pi와 비슷하게 시작한다.

도구설명주의점
read파일 읽기workspace 밖 접근 차단
write새 파일 작성overwrite 정책 필요
editdiff/patch 기반 수정idempotency test 필수
bash명령 실행allowlist/denylist, timeout, 출력 제한
grep텍스트 검색대용량 출력 제한
find파일 탐색.gitignore, ignore rule 반영
ls디렉터리 목록숨김 파일 정책

가장 중요한 것은 bash다. 단순히 명령을 실행할 수 있다고 보여주면 위험해 보인다. 반대로 다음 정책을 구현하면 포트폴리오 가치가 커진다.

CommandPolicy
  - default deny
  - read-only command allowlist
  - destructive command denylist
  - working directory jail
  - timeout
  - max stdout/stderr bytes
  - secret redaction
  - approval required flag
  - audit log

Pi README도 Pi가 기본적으로 filesystem, process, network, credential access를 제한하는 내장 permission system을 제공하지 않으며, 더 강한 경계가 필요하면 containerize/sandbox를 권장한다고 설명한다. Spring 버전에서 이 부분을 보완하면 "enterprise-safe Pi"라는 차별화가 생긴다.

Tool Search Advisor

도구 수가 늘어나면 모든 tool schema를 매번 모델에 보내는 방식은 비효율적이다. Spring AI의 Dynamic Tool Discovery 문서는 multi-server setup에서 50개 이상의 tool이 생기기 쉽고, 비슷한 이름의 tool이 30개 이상이면 tool selection accuracy가 떨어질 수 있다고 설명한다. Spring AI의 Tool Search Tool은 관련 tool만 동적으로 확장하는 방식이며, 문서상 34-64% token reduction을 제시한다.

처음에는 read/write/edit/bash만 두고, 이후 GitHub, DB, Jira, Slack, Notion, MCP tool이 늘어날 때 ToolSearchToolCallingAdvisor를 붙이는 흐름이 적절하다.

MCP

Pi는 MCP를 기본 내장하기보다 extension으로 다루는 쪽에 가깝다. 하지만 Spring AI 포트폴리오에서는 MCP를 넣는 편이 좋다.

Spring AI MCP 문서는 MCP를 AI model이 외부 tool과 resource를 구조적으로 다루게 하는 표준 프로토콜로 설명하며, Spring 개발자가 MCP server를 소비하는 client와 Spring service를 노출하는 server 양쪽에 참여할 수 있다고 설명한다.

권장 설계는 다음이다.

MCP Client
  -> 외부 GitHub/Postgres/Filesystem MCP tool 수집
  -> ToolRegistry 등록
  -> ToolSearchAdvisor로 관련 tool만 노출

MCP Server
  -> 내 Spring Agent의 read/edit/search/eval tool을 외부 client에 제공

구현 로드맵

시간 단위보다 산출물 단위로 진행한다.

Phase 0. Pi 분석 문서

산출물:

docs/00-pi-analysis.md
docs/01-spring-ai-mapping.md

내용:

  • Pi package 구조
  • agent event loop
  • tool execution lifecycle
  • session tree
  • project trust
  • extension/skill 개념
  • Spring AI 대응표

Phase 1. Hello Tool Agent

산출물:

GET /api/chat
GET /api/chat/stream
Tool: currentTime
Tool: readFile

기능:

  • ChatClient 기반 단순 질의
  • @Tool 기반 도구 호출
  • SSE streaming
  • model provider 설정 분리

Phase 2. Stateful Agent Runtime

산출물:

AgentRuntime.prompt()
Flux<AgentEvent>
AgentMessage
ToolCallEvent
ToolResultEvent

기능:

  • user/assistant/toolResult message 저장
  • turn 단위 실행
  • event streaming
  • tool call lifecycle
  • fake model provider 테스트

Phase 3. Coding Tools + Safety

산출물:

Tool: read
Tool: write
Tool: edit
Tool: bash
Tool: grep
Tool: find
Tool: ls
PolicyEngine
WorkspaceTrust

기능:

  • workspace jail
  • .gitignore 반영
  • path traversal 차단
  • destructive command 차단
  • timeout
  • max output limit
  • secret redaction
  • dry-run mode
  • approval required event

Phase 4. Session Tree + Compaction

산출물:

sessions/{sessionId}.jsonl
SessionNode(id, parentId)
fork
clone
compact
resume

기능:

  • JSONL session store
  • branch/fork
  • session replay
  • context compaction
  • compact summary validation

Compaction record는 이런 형태로 둘 수 있다.

{
  "type": "summary",
  "id": "...",
  "parentId": "...",
  "summary": {
    "objective": "...",
    "decisions": [],
    "filesTouched": [],
    "openQuestions": [],
    "constraints": []
  }
}

Phase 5. MCP + Dynamic Tool Discovery

산출물:

McpToolRegistry
ToolSearchAdvisor integration
External MCP server demo
Internal MCP server demo

기능:

  • 외부 MCP server tool을 ToolRegistry에 등록
  • tool이 많아지면 Tool Search Advisor로 관련 tool만 노출
  • 내 Spring tool을 MCP server로 노출

Phase 6. Observability + Evaluation

산출물:

AgentTrace
ToolExecutionMetrics
TokenUsageMetrics
RegressionEval
LLM-as-Judge Eval

평가는 두 갈래로 둔다.

평가설명
deterministic evalfake provider + expected tool call + expected patch
LLM-as-judge별도 평가 모델이 결과 품질을 채점

Spring AI는 ChatClient, Advisor, ChatModel, EmbeddingModel, VectorStore, Tool Calling에 대한 observation, metrics, tracing을 제공한다. agent 품질 측정은 이 계층에 regression eval과 LLM-as-Judge를 얹는 방식이 좋다.

학습 전략

Spring/Java 개발자 기준에서는 AI를 수학적으로 처음부터 공부하기보다, 백엔드 개발자의 강점을 살려 agent runtime을 설계하는 편이 좋다.

학습 원칙

  1. 문서 읽기보다 먼저 작은 agent slice를 만든다.
  2. 모든 기능은 테스트 가능한 단위로 만든다.
  3. 모든 단계는 설명 가능한 산출물을 남긴다.
  4. 모델 성능보다 runtime 설계, tool safety, observability를 강조한다.
  5. Python 생태계와 비교 경쟁하기보다 Java/Spring다운 운영 가능성을 보여준다.

공부 순서

단계공부 주제구현 과제산출물
1Pi 구조Pi 분석 문서Pi가 단순 CLI가 아닌 이유 정리
2Spring AI ChatClientHello agentSpring AI 2.0 시작 예제
3Tool CallingreadFile, listFilesTool Calling 흐름 정리
4Agent loopAgentRuntimeChatClient 자동화의 한계 정리
5File toolsread/write/editcoding agent tool 설계
6SafetyToolPolicyEngineagent sandboxing 정책
7SessionJSONL treesession 재현성과 fork
8Compactionsummary nodecontext window 관리
9MCPMCP client/serverJava에서 MCP 다루기
10Eval/Obsregression evalagent 품질 측정

이 방식에서 핵심은 공부한 내용을 바로 작은 구현으로 바꾸고, 구현한 내용을 다시 설명하면서 이해를 압축하는 것이다.

포트폴리오 데모

Demo 1. Repository Reader

요청: 이 프로젝트 구조를 분석해줘.
Agent:
  - ls
  - read README.md
  - read build.gradle.kts
  - summarize architecture

보여줄 것:

  • tool call event stream
  • read-only command policy
  • token usage

Demo 2. Failing Test Fixer

요청: 실패하는 테스트를 찾아서 고쳐줘.
Agent:
  - bash ./gradlew test
  - read failing test
  - edit source
  - bash ./gradlew test

보여줄 것:

  • bash timeout
  • edit patch
  • test result parsing
  • tool result 기반 다음 turn

Demo 3. Dangerous Command Block

요청: rm -rf . 해줘.
Agent:
  - bash tool call attempt
  - policy denied
  - 안전한 대안 제시

보여줄 것:

  • BeforeToolCallPolicy
  • audit log
  • 사용자 신뢰 확보

Demo 4. MCP Tool Discovery

요청: GitHub issue를 확인하고 관련 파일을 찾아줘.
Agent:
  - MCP GitHub tool discovery
  - ToolSearchAdvisor
  - selected tool execution

보여줄 것:

  • MCP client
  • dynamic tool search
  • tool schema 최소화

Demo 5. Session Fork

요청: 이 접근 대신 WebFlux SSE 방식으로 다시 설계해줘.
Agent:
  - previous node에서 fork
  - 새 branch 생성
  - 이전 결정 유지

보여줄 것:

  • JSONL session tree
  • parentId
  • replay
  • branch comparison

관련 논문과 아티클에서 가져올 포인트

자료핵심 아이디어프로젝트 반영
ReActreasoning trace와 action을 번갈아 수행해 외부 도구를 사용하는 패턴assistant -> tool call -> tool result -> next turn 루프
Toolformer모델이 어떤 API를 언제 어떻게 호출할지 학습/선택하는 관점tool description과 schema를 신중히 설계
Reflexion실패 경험을 verbal feedback과 episodic memory로 저장해 다음 시도에 반영session summary, failed attempt memory
SWE-agentcoding agent 성능은 agent-computer interface 설계에 크게 좌우됨edit, grep, bash, test feedback UX 개선
Anthropic Building Effective Agents복잡한 프레임워크보다 단순하고 조합 가능한 패턴을 권장처음부터 multi-agent가 아니라 단일 runtime부터 시작
OpenAI Agents/Responses APItool, tracing, guardrails, built-in agent primitives 강화observability와 guardrail을 핵심 기능으로 설계
MCPagent-to-tool 표준화MCP client/server module
A2Aagent-to-agent 상호운용후속 확장 아이디어
MCP 보안 논의tool poisoning, rug pull, 권한/정책 문제signed tool manifest, tool approval, policy-based access

추천 1차 완성 기준

처음부터 Pi 전체 복제를 목표로 잡으면 범위가 커진다. 1차 완성 기준은 아래 정도가 적절하다.

[필수]
- Spring AI 2.0 기반 ChatClient 연동
- OpenAI 또는 Anthropic 모델 1개
- Ollama 로컬 모델 1개
- read/write/edit/bash/grep/find/ls 도구
- ToolPolicyEngine
- WebFlux SSE event streaming
- JSONL session store
- parentId 기반 fork
- context compaction
- fake provider 기반 regression test
- README + architecture diagram + demo gif

[차별화]
- MCP client/server
- Tool Search Advisor
- OpenTelemetry tracing
- LLM-as-Judge evaluation
- Docker sandbox runner

[후속]
- CLI/TUI
- Git checkpoint
- plugin system
- A2A agent-to-agent 실험

가장 좋은 포지셔닝은 다음 문장이다.

Java/Spring 백엔드 개발자가 이해하고 운영할 수 있는 안전한 코딩 에이전트 런타임.

주의점

  • Spring AI의 최신 minor version, starter dependency, Boot 호환성은 빠르게 바뀔 수 있다. 실제 구현 시작 시점에 BOM과 starter dependency graph를 다시 확인해야 한다.
  • ChatClient의 자동 tool execution은 MVP에는 좋지만, 포트폴리오 차별화는 직접 만든 AgentRuntimeToolPolicyEngine에서 나온다.
  • bash, write, edit tool은 demo 가치가 크지만 위험하다. 기본 deny, workspace jail, timeout, output limit, audit log가 먼저다.
  • MCP는 확장성의 근거이지만 보안 표면도 넓힌다. tool discovery와 tool execution 사이에 policy gate를 둬야 한다.
  • "가브리엘 피터슨식 공부법"은 원문에서 신뢰 가능한 단일 출처를 확인하지 못했다고 밝힌 개념이다. 여기서는 문제 중심 학습, 작은 구현, 공개 설명, 피드백, 다음 난도 상승으로 해석했다.

검증이 필요한 주장

  • Spring AI 2.0.0 starter와 Spring Boot 4.0.x/4.1.x의 실제 dependency 충돌 여부는 프로젝트 생성 시점에 dependencyInsight나 Maven Enforcer로 다시 확인해야 한다.
  • Pi의 hook 이름, session 동작, tool execution lifecycle은 빠르게 변할 수 있으므로 구현 전 earendil-works/pi의 현재 README와 package 문서를 다시 확인해야 한다.
  • Tool Search Advisor의 34-64% token reduction은 Spring AI 문서와 블로그가 제시한 benchmark 맥락 안에서 해석해야 하며, 실제 프로젝트 tool set에서는 별도 측정이 필요하다.
  • MCP 보안 관련 preprint와 기사들은 출처 강도가 섞여 있다. 블로그나 포트폴리오에서 강한 보안 주장으로 쓰기 전에는 논문 상태와 재현 가능성을 확인해야 한다.
  • OpenAI Agents/Responses API, A2A, MCP 생태계 방향은 빠르게 바뀌므로 "업계 표준"처럼 단정하지 말고 2026년 현재의 흐름으로 표현해야 한다.

Source Fidelity Notes

  • Preserved key numbers: Spring AI 2.0.x, Spring Boot 4.0.x/4.1.x, Spring Boot 4.1.0, Java 17 이상, Java 26 호환 범위, Spring Framework 7.0.8 이상, tool 50개 이상, 유사 tool 30개 이상, 34-64% token reduction, Phase 0-6 로드맵, 5개 포트폴리오 데모.
  • Preserved frameworks / models: Pi Agent Harness, Spring AI ChatClient, ChatModel, Tool Calling, ToolCallingAdvisor, MCP, Tool Search Advisor, Observability, LLM-as-Judge, ReAct, Toolformer, Reflexion, SWE-agent, Anthropic agent patterns, OpenAI Agents/Responses API, A2A.
  • Preserved templates / checklists: Spring AI module layout, AgentRuntime 구성도, agent loop, CommandPolicy, Pi-to-Spring 매핑표, 구현 로드맵, 학습 순서, 포트폴리오 데모, 1차 완성 기준.
  • Omitted or compressed: 블로그용 시리즈 구성 섹션은 사용자 요청에 따라 공개 페이지에서 제외했다. 원문의 반복 설명, 일부 블로그 제목 제안, 긴 인용형 문장, utm_source가 붙은 보조 링크는 압축하거나 정리했다.
  • Omission risk: 블로그 시리즈 구조를 제외했기 때문에 글 발행 순서로 바로 쓰기에는 정보가 부족할 수 있다. 대신 프로젝트 설계와 학습 로드맵을 다시 읽기 위한 기술 노트로는 핵심 주장과 실행 항목을 보존했다. 원문은 sources/ layer에 별도 보존했다.

출처 / 참고자료