일반적인 요청 처리는 보통 실행을 시작하기 전에 입력 내용을 확정합니다. Agent의 실행은 여러 번의 모델 요청과 Tool 호출에 걸쳐 이어질 수 있으며, 그동안 사용자, 플러그인, 스케줄러 또는 다른 Agent가 새로운 정보를 계속 만들어 낼 수 있습니다.
따라서 “메시지를 한 번 더 보낸다”라는 말만으로는 Agent Runtime의 입력 작업을 충분히 설명할 수 없습니다.
Runtime은 최소한 다음 네 가지를 결정해야 합니다:
답이 어떻게 정해지는지에 따라 동작이 완전히 달라집니다.
모든 새 메시지가 곧바로 새로운 모델 실행 체인을 만들면 같은 Session을 여러 Loop이 동시에 수정하게 됩니다. 반대로 모든 메시지가 현재 작업이 완전히 끝날 때까지 기다리면 사용자는 진행 중인 방향을 제때 조정할 수 없습니다. Context가 바뀔 때마다 Agent를 자동으로 깨우면 불필요한 모델 호출이 대량으로 발생할 수도 있습니다.
따라서 Input Delivery는 Agent Runtime의 독립적인 설계 문제입니다.
Pi의 Steering / Follow-up Queue과 DeepSeek Harness의 Inbox은 각각 서로 다른 추상화 수준을 나타냅니다.
prompt()이 모든 입력을 담당할 수 없는 이유
먼저 가장 직접적인 API를 살펴보겠습니다.
Agent가 idle 상태라면 의미가 명확합니다. 새로운 능동 작업 구간을 시작하는 것입니다.
문제는 Agent가 이미 실행 중일 때 발생합니다.
현재 실행 흐름이 다음과 같다고 가정해 봅시다:
Model Request
↓
Tool Call
↓
Tool Execution
↓
Tool Result
↓
Next Model Request
이때 prompt(newMessage)를 한 번 더 호출하면 Runtime은 다음 중 하나를 결정해야 합니다:
A. 创建第二条并行 Loop
B. 取消当前 Loop,再启动新 Loop
C. 把消息加入当前 Loop 的下一次模型请求
D. 等当前 Loop 停止后再处理
네 가지 동작 모두 타당할 수 있지만, 모두 같은 암묵적 의미를 공유할 수는 없습니다.
Pi는 activeRun이 이미 있을 때 prompt()를 다시 호출하는 것을 직접 금지하며, 호출자가 steer(), followUp(), abort() 중 하나를 명시적으로 선택하도록 요구합니다.[1]
이 제약은 동시 입력 문제를 “Runtime이 스스로 추측하는 문제”에서 “호출자가 의도를 명확히 표현하는 문제”로 바꿉니다.
입력 제어는 먼저 실행 경계에 의존한다
앞선 두 글에서는 이미 두 가지 핵심 경계를 세웠습니다:
Step Boundary
一次模型决策及其 Tool 工作结束
Turn Boundary
当前连续工作到达停止点
Input Delivery의 의미는 사실상 이 두 경계 위에 구축됩니다.
Runtime이 Step과 Turn조차 안정적으로 정의하지 못한다면 다음을 정확히 설명하기 어렵습니다:
“尽快生效”到底是现在,还是下次模型调用前
“当前工作结束以后”到底在哪个时刻
따라서 Steer와 Follow-up은 서로 다른 실행 시점에 대응하며, 분류 기준은 Step과 Turn 경계에서 나옵니다.
Pi는 두 개의 Queue로 두 시점을 직접 표현한다
Pi의 Agent는 현재 다음을 유지합니다:
두 Queue 모두 one-at-a-time과 all의 두 drain mode를 지원하며, 기본적으로 한 번에 메시지 하나씩 소비합니다.[1]
공개 API는 다음과 같습니다:
두 API의 가장 핵심적인 차이는 소비 시점입니다.
Steering: 가장 가까운 다음 모델 결정에 영향을 준다
Pi RPC 문서는 Steering의 전달 시점을 매우 구체적으로 정의합니다. Agent가 작업 중일 때 Steering Message는 먼저 Queue에 들어가며, 현재 Assistant Turn에서 생성된 Tool Calls가 실행을 마친 뒤 다음 LLM Call 직전에 전달됩니다.[2]
실행 순서는 다음과 같이 나타낼 수 있습니다:
여기에는 두 가지 핵심이 있습니다.
첫째, Steering은 이미 Provider에 제출된 Model Request를 수정하지 않습니다. 모델이 생성을 시작하면 해당 요청에 사용되는 Context는 이미 확정된 상태입니다.
둘째, Steering은 현재 Tool을 기본적으로 중단하지도 않습니다. Tool Call은 앞선 모델 결정에서 이미 발생한 Effect이므로, Pi는 이를 먼저 완료시킨 뒤 새 입력을 다음 모델 결정에 넣습니다.
따라서 Steering의 의미는 다음과 같이 더 정확히 표현할 수 있습니다:
현재 시작된 작업을 훼손하지 않는다는 전제하에, 새 입력이 가능한 한 빨리 후속 모델 결정에 영향을 주도록 합니다.
이것이 Step Boundary의 가치입니다.
왜 Steering이 Cancel과 암묵적으로 같아서는 안 되는가
사용자가 “이 방향으로 더 진행하지 마세요”라고 입력하면 제품 계층은 Tool을 즉시 중단하기를 원할 수 있습니다. 반면 다른 입력은 조건만 보충하는 것이라 현재 작업을 취소할 필요가 없습니다.
예를 들어:
“接下来不要修改测试文件”
현재 Tool이 끝난 뒤 다음 단계에 영향을 주어도 됩니다.
반면:
“停止执行”
보통 현재 활성 작업을 바로 취소해야 합니다.
모든 Steering이 암묵적으로 Cancel을 유발하면 보충 정보 하나만으로도 현재 Tool의 완결성이 깨집니다. 반대로 모든 Steering이 절대로 취소할 수 없다면 긴급 중단을 표현할 방법이 없습니다.
따라서 Pi는 두 가지 제어를 분리합니다:
steer
改变后续决策
abort
终止当前活动
이렇게 분리하면 메시지 텍스트에서 사용자 의도를 추론하려는 것보다 안정적입니다.
Follow-up: 현재 연속 작업이 정지점에 도달할 때까지 대기한다
Follow-up의 시점은 더 늦습니다.
Pi는 현재 Tool Calls와 Steering Messages가 모두 없고 Agent 작업을 끝내려는 시점에야 Follow-up Queue를 소비합니다.[2]
Current Work
├── Model
├── Tool
├── Model
└── Final
↓
Stop Boundary
↓
Follow-up Queue
↓
Next Work
따라서 Follow-up은 다음과 같은 의미에 적합합니다:
当前工作保持完整
完成以后继续处理新的要求
Pi runLoop()의 2단계 루프가 바로 이 의미를 인코딩합니다.[3]
Inner Loop
Tool + Steering
Outer Loop
Follow-up
이는 “모든 메시지를 하나의 FIFO Queue에 넣는다”보다 명시적인 실행 관계를 한 단계 더 제공합니다.
두 개의 Queue만으로 이미 단순한 Delivery Model이 구성된다
데이터 구조만 보면 Steering Queue과 Follow-up Queue은 모두 처리 대기 메시지 목록입니다.
진짜 의미 있는 부분은 두 Queue가 서로 다른 소비 지점에 묶여 있다는 것입니다:
steeringQueue
→ next decision boundary
followUpQueue
→ stop boundary
따라서 Pi는 이미 두 Delivery Target을 표현하고 있습니다. Target이 서로 다른 Queue와 API에 직접 인코딩되어 있을 뿐입니다.
이 설계의 장점은 단순함입니다.
호출자는 다음 중 하나만 선택하면 됩니다:
Runtime 내부에서도 추가 필드를 해석할 필요가 없습니다. Queue 자체가 의미를 나타내기 때문입니다.
대신 전달 전략이 계속 늘어날수록 API와 Queue의 수 역시 늘어날 수 있다는 비용이 있습니다.
예를 들어 시스템이 다음도 표현하고 싶다고 하면:
加入下一次 Context,但不要主动启动 Agent
只在某个 Tool 完成后可见
高优先级插队
只对某个子 Agent 生效
고정된 두 Queue만으로는 한계가 생깁니다.
DeepSeek Harness는 이 의미 층을 한 단계 더 매개변수화하는 쪽을 택했습니다.
DeepSeek Harness는 Inbox로 입력 진입점을 통일한다
DeepSeek Harness는 현재 공개하는 Agent API로 다음을 제공합니다:
여기서:
followup(), steer(), inject()는 서로 다른 매개변수 조합을 편리하게 감싼 API로 볼 수 있습니다.[4]
그러면 입력을 다음과 같이 분해할 수 있습니다:
Payload
+
Target
+
Wakeup
↓
Inbox
이 단계는 Pi의 두 Queue보다 추상화 계층을 하나 더 둡니다.
Pi에서는 API 이름 자체가 전달 방식을 나타내지만, DSH는 전달 방식을 데이터에 명시적으로 인코딩합니다.
target은 입력이 어느 실행 경계에 속하는지 설명한다
target = next-step은 이 입력이 가장 가까운 Step 경계에서 후속 모델 결정에 포함되어야 함을 뜻합니다.
target = next-turn은 입력이 현재 Turn이 끝날 때까지 기다린 뒤 후속 작업으로 소비된다는 뜻입니다.
그러면 Pi의 두 개념을 다음과 같이 대응시킬 수 있습니다:
steer
≈ next-step
follow-up
≈ next-turn
여기서는 “약 같다”는 표현이 더 정확합니다. 프레임워크마다 idle 상태, wakeup, lifecycle hook에 대한 구체적인 의미가 다르기 때문입니다.
핵심은 같습니다. 입력은 자신이 어느 실행 시점에 속하는지 표시해야 합니다.
동일한 입력도 idle과 running 상태에 따라 다른 결과를 낳을 수 있다
Delivery Policy는 Agent의 현재 상태와 결합해 해석해야 합니다.
먼저 단순화한 행렬로 나타내면 다음과 같습니다:
가장 중요한 점은 target이 시점을, wakeup이 활성화 권한을 나타낸다는 것입니다. 둘을 결합해야 Runtime이 현재 상태에서 실제 동작을 결정할 수 있습니다.
API가 send(message)만 제공한다면 이 차이는 구현 내부에 숨겨질 수밖에 없습니다. idle 상태에서는 자동으로 시작하고 running 상태에서는 자동으로 큐에 넣는 방식이 편리해 보이지만, 호출자는 어떤 메시지가 현재 작업에 들어가는지, 후속 작업을 만드는지 알기 어렵습니다.
명시적인 Policy는 프로토콜을 조금 복잡하게 만들지만 상태에 종속된 암묵적 동작은 방지합니다. SDK, RPC, Web UI, 플러그인이 함께 호출하는 Runtime이라면 이런 안정성이 대체로 더 중요합니다.
wakeup은 왜 독립적인 차원이 되어야 하는가
target만으로 충분하지 않습니다.
Runtime은 다음 Context에 영향을 주어야 하는 정보를 받을 수 있지만, 그 때문에 즉시 Model Request를 시작하고 싶지는 않을 수 있습니다.
예를 들어:
文件索引更新
环境变量变化
插件补充新的上下文
异步任务返回一段参考信息
이런 정보는 다음 모델 계산에 포함될 수 있지만, Agent가 현재 idle 상태라면 즉시 깨울 필요는 반드시 없습니다.
모든 Inbox Message가 자동으로 실행을 시작한다면:
background state changed
↓
message appended
↓
agent wakes
↓
model request
시스템은 “상태 업데이트”와 “작업 생성”을 하나로 묶어 버립니다.
DeepSeek Harness가 wakeup을 독립시킨 뒤에는 다음과 같이 표현할 수 있습니다:
next-step + wakeup=false
只影响未来 Context
next-turn + wakeup=true
形成需要执行的新工作
이를 통해 “모델이 무엇을 보아야 하는가”와 “Agent가 지금 실행을 시작해야 하는가”를 서로 다른 제어 차원으로 둘 수 있습니다.
inject()의 의미는 바로 여기에 있다
inject(message)는 wakeup을 독립시킨 뒤의 가치를 가장 잘 보여 줍니다.
정보를 후속 Context에 추가하되 Agent를 능동적으로 깨우지 않을 수 있게 해 줍니다.[4]
Agent가 이미 running 상태라면 이 입력은 적절한 Step Boundary에서 claim될 수 있습니다. Agent가 idle 상태라면 Inbox에 남아 있다가 나중에 실제로 작업을 시작할 수 있는 입력을 기다립니다.
따라서 세 가지 연산을 다음과 같이 이해할 수 있습니다:
구체적인 구현 세부 사항은 여전히 각 프레임워크의 현재 정의를 따라야 하지만, 설계 관점에서 DSH는 입력을 “채팅 메시지”에서 Runtime Mailbox 안의 작업 신호로 확장했습니다.
Input, Wakeup, Cancel은 세 가지 차원으로 분리해야 한다
Pi와 DSH를 함께 놓고 보면 더 일반적인 제어 모델을 얻을 수 있습니다.
외부 입력 하나에는 최소한 다음 세 가지 서로 독립적인 질문이 들어 있습니다:
Content
模型或 Runtime 要接收什么信息
Delivery
这条信息在什么边界生效
Activation
这条信息是否触发 Agent 从 idle 进入 active
Cancel은 네 번째 차원에 해당합니다:
Interruption
是否终止当前已有工作
다음과 같이 표현할 수도 있습니다:
반드시 두 인터페이스로 실제로 나눌 필요는 없습니다. 중요한 것은 sendMessage()이라는 동작 하나에 모든 의미를 숨기지 않는 것입니다.
Runtime이 자연어로 Delivery를 자동 추측하게 하면 안 되는 이유
제품은 UI에서 일반 Enter, Steer, Follow-up, Stop을 서로 다른 버튼으로 만들 수 있고, 상위 Agent가 자동으로 전략을 고르게 할 수도 있습니다.
그러나 하위 Runtime은 이미 결정된 전달 의미를 받는 편이 가장 좋습니다.
Runtime이 메시지 텍스트를 추론한다면:
“顺便补充一下……”
→ follow-up ?
“先别这样做……”
→ steer ? abort ?
동작이 언어 이해 모델에 의존하게 되고, 호출자에게 안정적인 계약을 제시하기 어려워집니다.
더 신뢰할 수 있는 분층은 다음과 같습니다:
UI / Orchestrator
决定用户意图和 Delivery Policy
↓
Agent Runtime
严格执行 Delivery Policy
이렇게 하면 Runtime은 결정성을 유지할 수 있습니다.
Queue의 drain mode도 전달 의미에 속한다
Pi의 PendingMessageQueue는 one-at-a-time과 all의 두 drain mode를 지원합니다.[1]
이 세부 사항은 “next-step”을 정했더라도 배치 처리 정책이 여전히 필요하다는 점을 보여 줍니다.
Step 실행 중 Steering 세 개가 연속으로 들어온다고 가정해 봅시다:
S1
S2
S3
all 모드는 다음 모델 요청 전에 모든 입력을 한 번에 추가할 수 있습니다:
Tool Result
+ S1
+ S2
+ S3
→ Model Request
one-at-a-time은 메시지 하나만 소비하고, 나머지 입력은 이후의 결정 경계에서 계속 들어오게 할 수도 있습니다.
두 전략은 모델이 정보를 받아들이는 리듬과 사용자가 “연속으로 보충한 요구”를 체감하는 방식에 모두 영향을 줍니다.
따라서 Delivery Policy는 다음과 같이 더 확장할 수도 있습니다:
이 필드들이 필요한지는 제품 복잡도에 달렸습니다. 핵심 추상화는 여전히 전달 시점을 명시화하는 것입니다.
Inbox는 왜 메모리 Queue에서 관찰 가능한 상태로 발전했을까
DeepSeek Harness는 현재 Inbox를 Agent-owned durable projection으로 설명합니다. next-turn과 next-step의 두 개의 순서 있는 pending-message list를 유지하며, append, replace, remove, clear, splice, claim 같은 연산은 정규화된 mutation event를 만듭니다.[4]
이는 Inbox가 런타임 스케줄링만 맡는다는 뜻이 아닙니다.
외부 시스템은 다음을 관찰할 수도 있습니다:
当前有哪些输入正在等待
每条输入属于 next-step 还是 next-turn
哪些输入已经被 claim
哪些输入被删除或替换
그러면 UI가 pending instructions를 표시하고, 복구 로직도 대기 상태를 재구성할 수 있습니다.
일반적인 메모리 Queue의 책임은 보통 다음뿐입니다:
enqueue
→ dequeue
DSH Inbox는 Agent-owned Mailbox State에 더 가깝습니다.
이는 DSH의 Event / Projection 접근이 실행 제어 계층으로 확장된 것도 의미합니다.
두 번째 단원에서 Session Event Log를 다룰 때 이러한 durable projection을 더 깊이 살펴보겠습니다.
입력 출처가 늘어나면 Mailbox 추상화가 Chat Queue보다 안정적이다
초기 Agent 제품의 입력은 보통 User Message뿐이었습니다. Harness의 기능이 늘어나면서 입력 출처는 다음과 같이 확장됩니다:
User
Plugin
Scheduler
SubAgent
External Event
Approval System
하지만 이러한 입력이 모두 사용자에게 보이는 채팅 메시지로 표시될 필요는 없습니다.
예를 들어 스케줄러는 백그라운드 작업을 실행하도록 Agent를 깨우기만 하면 되고, 플러그인은 다음 Context에 환경 사실을 주입하기만 하면 됩니다. SubAgent가 반환한 결과는 상위 Agent의 현재 Step에 들어가야 할 수도 있습니다.
Runtime의 핵심 인터페이스가 여전히 “Chat Message”만 허용한다면, 상위 계층은 온갖 제어 정보를 User Message로 위장하는 경우가 많습니다. 결국 대화 이력이 제어 프로토콜과 UI 표시를 동시에 담당하게 됩니다.
Mailbox / AgentInput 모델은 Payload를 더 일반화할 수 있게 합니다:
Delivery Policy는 여전히 각각이 언제 소비될지를 결정합니다.
이렇게 하면 입력 경로는 “채팅 큐”에서 Runtime의 통합 외부 이벤트 진입점으로 진화하면서도, Context Builder가 어떤 입력을 최종적으로 모델에 보이는 Message로 바꿀지 결정할 수 있습니다.
오래 실행되는 Tool은 Steering 경계의 비용을 드러낸다
Steering이 현재 Tool의 완료를 기다린 뒤 적용되는 것은 의미가 명확하지만, 분명한 비용도 있습니다.
어떤 Tool이 오래 실행된다면:
사용자는 Steering이 충분히 즉각적이지 않다고 느낄 수 있습니다.
여기서 Steer의 의미를 단순히 바꿔 실행 중인 Tool에 강제로 끼어들게 해서는 안 됩니다. 더 합리적인 처리 방법은 보통 다음과 같습니다:
Tool 支持 AbortSignal
+
产品允许用户显式 Stop
+
必要时 Stop 后再提交新的 Steer / Prompt
또는 대화형 Tool에 대해 더 세밀한 내부 제어 프로토콜을 정의할 수도 있습니다.
이는 Step Boundary가 주는 안정성에도 비용이 있음을 보여 줍니다. 경계가 거칠수록 새 입력에 대한 응답 지연이 길어질 수 있습니다.
Agent Runtime의 제어 설계는 “상태 일관성”과 “상호작용의 즉시성” 사이에서 적절한 세분성을 선택해야 합니다.
여러 Tool이 동시에 실행될 때는 먼저 Step 완료 조건을 정의해야 한다
또 하나의 경계 문제는 하나의 Assistant Message가 여러 Tool Call을 동시에 생성하는 경우입니다.
Assistant
├── Tool A
├── Tool B
└── Tool C
A, B, C가 동시에 실행될 때 Steering은 A가 끝나자마자 들어와야 할까요, 아니면 전체 Tool Batch이 완료될 때까지 기다려야 할까요?
이는 Runtime이 Step을 어떻게 정의하느냐에 달려 있습니다.
Pi RPC 문서는 현재 Assistant Turn의 Tool Calls가 실행을 마친 뒤 Steering을 전달한다고 설명합니다.[2]
따라서 다음과 같이 이해할 수 있습니다:
Model Decision
↓
Tool Batch
↓ all relevant tool calls complete
Step Boundary
↓
Steering
이 선택은 Steering이 동일한 모델 결정에서 생성된 Tool Effect의 절반에만 영향을 미치는 일을 막아 줍니다.
어떤 Runtime이 더 세밀한 제어를 원한다면 Tool Batch을 명시적인 하위 단계로 다시 나누어야 합니다. 그러지 않으면 동작이 일관되지 않게 됩니다.
직접 Runtime을 설계할 때 Delivery Policy를 어떻게 표현할 수 있는가
Pi와 DSH의 구현에서 한 걸음 더 추상화하면 다음과 같이 정의할 수 있습니다:
처음부터 모든 필드를 구현할 필요는 없습니다.
최소 버전에는 다음 두 개만 필요합니다:
이만으로도 세 가지 일반적인 의미를 모두 다룰 수 있습니다:
next-step + wakeup=true
尽快改变后续决策
next-turn + wakeup=true
当前工作完成后继续
next-step + wakeup=false
只注入后续 Context
Cancel은 독립적인 제어 API로 유지합니다.
나중에 다중 출처, 우선순위, 타임아웃, 지속성 요구가 생기면 Delivery Policy를 확장하면 됩니다.
UI는 의도를 드러내고, Runtime은 실행 의미를 담당해야 한다
Input Delivery는 결국 제품 상호작용에 반영됩니다.
숙련된 Agent UI는 다음을 동시에 제공할 수 있습니다:
Send
正常发起工作
Steer
调整当前工作后续方向
Queue / Follow-up
排在当前工作之后
Stop
立即取消当前执行
이 버튼들은 UI상의 차이일 뿐 아니라 서로 다른 Runtime API에 대응합니다.
따라서 프런트엔드는 다음만 유지해서는 안 됩니다:
그다음 백엔드가 현재 상태에 맞는 처리 방법을 스스로 추측하게 해서는 안 됩니다.
더 안정적인 프로토콜은 명시적인 액션이나 Delivery Policy를 함께 전달합니다:
백엔드는 합의한 규칙대로 Inbox에 넣고 올바른 경계에서 claim하면 됩니다.
덕분에 UI, Transport, Runtime이 같은 동작에 대해 일관된 의미를 갖게 됩니다.
Delivery Policy는 관찰 가능성도 유지해야 한다
입력이 Queue나 Inbox에 들어가면 외부 시스템은 일반적으로 현재 상태를 알아야 합니다. 그렇지 않으면 UI는 “전송됨”만 표시할 수 있을 뿐, 메시지가 이미 모델에 들어갔는지, 아직 대기 중인지, 취소로 버려졌는지 구분할 수 없습니다.
관찰 가능한 입력 생명 주기는 다음과 같이 작게 유지할 수 있습니다:
PENDING
↓ claim
CONSUMED
PENDING
↓ remove / cancel
DISCARDED
시스템이 Event Log를 채택한다면 input/queued, input/claimed, input/removed 같은 사실도 기록할 수 있습니다.
이런 상태는 모델 추론 자체에는 직접적인 가치가 없지만 UI, 복구, 디버깅에는 매우 중요합니다. Input Delivery가 실행 계층과 제품 계층을 동시에 연결한다는 사실도 드러냅니다. 실행 계층은 언제 claim할지, 제품 계층은 입력이 여전히 유효한지에 관심이 있습니다.
Input Delivery와 Agent Loop의 연결 위치
이 단원의 전체 모델을 한데 놓으면 다음과 같습니다:
여기에는 두 가지 제어 방향이 있습니다:
Input Delivery
决定新的信息何时进入
Execution Control
决定已有工作是否继续
둘을 분리하면 Steer, Follow-up, Inject, Abort의 경계를 훨씬 안정적으로 정할 수 있습니다.
1단원에서 도출한 실행 모델
네 편의 글에 걸친 내용은 다음과 같은 완전한 Runtime 관계로 정리할 수 있습니다:
첫 번째 글은 Runtime이 왜 등장했는지 다뤘고, 두 번째 글은 다층 생명주기를 세웠으며, 세 번째 글은 Pi 소스로 Loop과 State가 어떻게 진행되는지 검증했습니다. 네 번째 글은 실행 중 들어오는 새 입력을 명시적인 Delivery Model에 넣었습니다.
이 글에서 마지막으로 남기는 설계 판단은 다음과 같습니다:
Agent 입력은 내용과 전달 의미를 동시에 기술해야 합니다. Delivery Target, Wakeup, Cancellation은 서로 다른 제어 차원입니다. 이를 명시화하면 Runtime이 현재 암묵적 상태를 바탕으로 메시지가 어떻게 적용되어야 하는지 추측하는 일을 피할 수 있습니다.
다음 단원에서는 지속성을 다룹니다. 실행 모델이 정리된 뒤에는 어떤 상태를 장기적인 사실로 저장해야 하고 어떤 상태는 복구 시 다시 계산할 수 있는지 더 살펴봐야 합니다. Pi는 왜 Session을 트리로 표현했고, DeepSeek Harness는 왜 Event Log를 Session의 사실 공급원으로 선택했는지도 다룹니다.
참고자료
[1] Pi Agent 소스: https://github.com/badlogic/pi-mono/blob/main/packages/agent/src/agent.ts
[2] Pi RPC 문서: https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/docs/rpc.md
[3] Pi agent-loop.ts: https://github.com/badlogic/pi-mono/blob/main/packages/agent/src/agent-loop.ts
[4] DeepSeek Harness Core / Agent Inbox: https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/core.md
[5] DeepSeek Harness Agent Lifecycle: https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/agent-lifecycle.md