Codex CLI /goal 내부 구조 분석
메뉴

AI Agent

Codex CLI /goal 내부 구조 분석

Codex CLI /goal 기능을 state DB, app server API, model tools, core runtime, continuation prompt 관점에서 코드 레벨로 분석합니다.

Codex CLI /goal 내부 구조 분석 hero image
Markdown약 4125 tokens

thread_goals, continuation runtime, completion audit까지 코드 레벨로 보기

1편에서는 Codex CLI /goal을 사용자 관점에서 봤습니다. 이번 글에서는 내부 구조를 봅니다.

핵심은 간단합니다.

# 읽기 가이드: 아래 블록은 명령, 상태 흐름, 또는 템플릿 예시입니다./goal은 명령 하나가 아니다.목표 상태 저장소, app-server API, model tool, runtime continuation, TUI 제어가 결합된 기능이다.

이 글은 Codex GitHub PR과 공개된 소스 파일을 기준으로 작성했습니다. 출시 직후 기능이므로 실제 구현은 이후 버전에서 달라질 수 있습니다.

분석 기준일: 2026-05-02
기준 버전: Codex CLI 0.128.0
주요 참고자료: OpenAI Codex changelog, GitHub PR #18073–#18077, thread_goals migration, continuation.md, budget_limit.md


핵심 요약

  • /goalTUI command → app-server API → model tools → core runtime → state DB로 이어지는 5개 레이어 기능입니다.
  • goal 상태는 thread_goals 테이블에 저장되며, status는 active, paused, budget_limited, complete로 제한됩니다.
  • model tool은 goal을 마음대로 조작하지 못합니다. update_goal은 완료 처리 중심으로 제한되고, pause/resume/clear/budget-limited 전이는 사용자 또는 runtime 제어에 남습니다.
  • core runtime은 GoalRuntimeEvent를 통해 turn start, tool completion, turn finish, interrupt, resume, idle continuation을 처리합니다.
  • continuation prompt는 완료 전 “현재 실제 상태”를 기준으로 completion audit을 수행하라고 요구합니다.
  • 좋은 agent 설계 관점에서 /goal의 핵심은 while true가 아니라 event-driven continuation + evidence audit + budget guard입니다.

1. 전체 구조: 5개 레이어로 보기

코드 기준으로 /goal은 아래 구조에 가깝습니다.

# 읽기 가이드: 아래 블록은 명령, 상태 흐름, 또는 템플릿 예시입니다.TUI /goal commandapp-server thread/goal APImodel tools: get_goal / create_goal / update_goalcore runtime: continuation / accounting / interrupt / resumestate DB: thread_goals table

각 레이어의 역할은 다릅니다.

레이어역할핵심 포인트
TUI사용자가 /goal을 만들고 멈추고 지우는 UIcommand와 상태 표시
app-serverclient가 thread goal 상태를 제어하는 APIget/set/clear, notification, resume snapshot
model tools모델이 goal을 조회·생성·완료 처리하는 도구권한 제한이 중요
core runtimecontinuation, accounting, interrupt, resume 처리실제 “계속 작업”을 만드는 중심
state DBgoal objective/status/usage 저장thread 단위 persistence

이 구조를 보면 /goal이 단순히 “모델에게 계속하라고 말하는 프롬프트”가 아니라는 점이 분명합니다. 목표 상태는 DB에 있고, runtime은 턴 생명주기에 맞춰 그 상태를 갱신합니다.


2. State DB: thread_goals 테이블

가장 아래에는 thread_goals 테이블이 있습니다. 공개 migration 기준으로 이 테이블은 다음 정보를 저장합니다.

컬럼의미
thread_idgoal이 붙은 thread 식별자
goal_idgoal 자체의 식별자
objective사용자가 지정한 목표
statusactive, paused, budget_limited, complete 중 하나
token_budget선택적 token budget
tokens_usedgoal 수행 중 누적 token 사용량
time_used_secondsgoal 수행 중 누적 시간
created_at_ms생성 시각
updated_at_ms갱신 시각

의사 타입으로 쓰면 이렇게 볼 수 있습니다.

// 읽기 가이드: 실제 API가 아니라 구조를 설명하는 의사코드입니다.type ThreadGoal = {  thread_id: string  goal_id: string  objective: string  status: "active" | "paused" | "budget_limited" | "complete"  token_budget?: number  tokens_used: number  time_used_seconds: number  created_at_ms: number  updated_at_ms: number}

여기서 중요한 건 thread_id입니다. goal은 단순 메모리 플래그가 아니라 thread 상태에 붙어 있습니다. 그래서 resume, reconnect, app-server snapshot 같은 기능과 연결될 수 있습니다.

또 하나 중요한 건 goal_id입니다. PR #18073 설명에 따르면 stale update protection이 들어갔습니다. 즉 오래된 goal update가 새 goal을 덮어쓰지 못하도록 막는 장치입니다.

# 읽기 가이드: 아래 블록은 명령, 상태 흐름, 또는 템플릿 예시입니다.문제:- goal A가 진행 중이다.- 사용자가 goal B로 교체한다.- 늦게 도착한 goal A update가 goal B 상태를 덮어쓴다. 해결:- update 시 expected goal_id를 확인한다.- 현재 goal_id와 다르면 stale update로 보고 막는다.

AI agent runtime에서 이런 보호는 중요합니다. 여러 async task, tool result, user mutation이 섞이면 “늦게 도착한 업데이트”가 상태를 망가뜨릴 수 있기 때문입니다.


3. App-server API: thread goal 제어면

두 번째 레이어는 app-server API입니다. PR #18074는 v2 API로 다음 RPC와 notification을 추가했다고 설명합니다.

# 읽기 가이드: 아래 블록은 명령, 상태 흐름, 또는 템플릿 예시입니다.RPC:- thread/goal/get- thread/goal/set- thread/goal/clear Notification:- thread/goal/updated- thread/goal/cleared

이 API가 필요한 이유는 client가 goal 상태를 안정적으로 읽고 제어해야 하기 때문입니다.

API 요소역할
thread/goal/get현재 thread의 goal 상태 조회
thread/goal/setgoal 설정 또는 상태 변경
thread/goal/cleargoal 제거
thread/goal/updatedgoal 변경을 client에 알림
thread/goal/clearedgoal 삭제를 client에 알림
resume/snapshot wiringreconnect한 client가 현재 goal 상태를 볼 수 있게 함

이 레이어가 있으면 TUI뿐 아니라 다른 client도 동일한 goal 상태를 볼 수 있습니다. 즉 /goal은 TUI 전용 hack이 아니라 app-server를 통해 materialized thread goal을 다루는 구조입니다.


4. Model tools: 제한된 모델 권한

세 번째 레이어는 model-facing tool입니다. PR #18075에 따르면 goal 관련 tool은 다음 세 가지입니다.

# 읽기 가이드: 아래 블록은 명령, 상태 흐름, 또는 템플릿 예시입니다.get_goalcreate_goalupdate_goal

여기서 설계가 흥미롭습니다. 모델이 goal을 무제한으로 조작할 수 있게 하지 않았습니다.

Tool허용된 역할제한
get_goal현재 goal 확인read 중심
create_goal명시적으로 요청된 goal 생성기존 goal이 없을 때만 생성하도록 제한
update_goalgoal 완료 처리completion 중심으로 제한

PR 설명은 pause, resume, clear, budget_limited 전이를 모델이 마음대로 처리하지 않고 사용자 또는 runtime-controlled 상태로 남겨둔다고 설명합니다.

이 설계는 중요합니다.

모델에게 모든 상태 제어권을 주면 이런 문제가 생길 수 있습니다.

# 읽기 가이드: 아래 블록은 명령, 상태 흐름, 또는 템플릿 예시입니다.- 모델이 스스로 pause 처리해서 작업을 회피한다.- 예산 초과 상태를 모델이 임의로 해제한다.- 사용자가 만든 goal을 모델이 clear한다.- 완료되지 않았는데 complete로 표시한다.

그래서 /goal은 모델이 작업을 수행하고 완료를 선언할 수는 있지만, 사용자 제어와 runtime 제어를 분리합니다.

# 읽기 가이드: 아래 블록은 명령, 상태 흐름, 또는 템플릿 예시입니다.모델 권한: 조회, 명시적 생성, 완료 처리사용자 권한: pause, resume/unpause, clear, replacementruntime 권한: budget_limited, accounting, continuation scheduling

이 권한 분리는 agent 시스템을 만들 때 그대로 참고할 만합니다.


5. Core runtime: continuation 상태 머신

네 번째 레이어가 가장 중요합니다. PR #18076은 long-running goal을 client가 아니라 core runtime concern으로 봅니다. core가 turn lifecycle, tool completion boundaries, interruptions, resume behavior, token usage를 관리하기 때문입니다.

공개 코드의 goals.rs 주석을 보면 이 모듈은 core session과 state DB goal table을 연결하고, goal mutation 검증, protocol 변환, goal-update event 발행, lifecycle hook을 담당합니다.

핵심 이벤트는 다음처럼 볼 수 있습니다.

# 읽기 가이드: 아래 블록은 명령, 상태 흐름, 또는 템플릿 예시입니다.GoalRuntimeEvent- TurnStarted- ToolCompleted- ToolCompletedGoal- TurnFinished- MaybeContinueIfIdle- TaskAborted- ExternalMutationStarting- ExternalSet- ExternalClear- ThreadResumed

의사코드로 정리하면 이렇습니다.

// 읽기 가이드: 실제 API가 아니라 구조를 설명하는 의사코드입니다.on TurnStarted:  capture token usage baseline  if current thread has active goal:    mark goal active for this turn on ToolCompleted:  account token/time usage  reset no-tool continuation suppression  if token budget exceeded:    mark goal as budget_limited    inject budget wrap-up steering on TurnFinished:  account final usage  if this was a continuation turn and tool_calls == 0:    suppress next automatic continuation on MaybeContinueIfIdle:  if session is idle and active goal exists:    start continuation turn on TaskAborted with interrupt:  account usage  pause active goal on ThreadResumed:  reactivate paused goal outside plan mode

여기서 /goal의 실체가 드러납니다. Codex가 “계속 작업하는 것처럼 보이는 이유”는 모델이 혼자 무한 루프를 돌기 때문이 아니라, core runtime이 idle 상태에서 continuation turn을 예약하기 때문입니다.

# 읽기 가이드: 아래 블록은 명령, 상태 흐름, 또는 템플릿 예시입니다.active goal exists+ session is idle+ not suppressed+ budget not exhausted= start continuation turn

6. Continuation prompt: 완료 감사의 핵심

continuation.md 템플릿은 /goal 품질의 핵심입니다.

이 prompt는 먼저 active thread goal을 계속 수행하라고 지시합니다. 동시에 objective를 “user-provided data”로 취급하라고 명시합니다. 즉 goal 문구가 system instruction처럼 승격되는 구조가 아닙니다.

또 매 continuation마다 다음 정보를 넣습니다.

# 읽기 가이드: 아래 블록은 명령, 상태 흐름, 또는 템플릿 예시입니다.Time spent pursuing goalTokens usedToken budgetTokens remaining

가장 중요한 부분은 completion audit입니다. prompt는 완료를 선언하기 전에 다음을 하라고 요구합니다.

요구의미
objective를 concrete deliverables/success criteria로 재정리목표를 검증 가능한 형태로 바꿈
모든 explicit requirement를 evidence checklist에 매핑요구사항 누락 방지
파일, 명령 출력, 테스트 결과, PR 상태 등 실제 증거 확인말이 아니라 현재 상태 기준으로 판단
proxy signal만으로 완료 처리하지 않기“테스트 통과”도 목표 전체를 커버할 때만 증거
불확실하면 완료가 아니라 계속 작업애매한 상태에서 premature complete 방지

이 부분은 AI agent 설계에서 매우 중요합니다.

나쁜 agent loop는 이렇게 끝납니다.

# 읽기 가이드: 아래 블록은 명령, 상태 흐름, 또는 템플릿 예시입니다.테스트 하나 통과함→ 아마 됐겠지→ complete

좋은 goal runtime은 이렇게 끝나야 합니다.

# 읽기 가이드: 아래 블록은 명령, 상태 흐름, 또는 템플릿 예시입니다.목표 요구사항 목록화→ 각 요구사항을 실제 evidence와 매핑→ 누락/미검증 항목 확인→ 모두 충족되면 complete→ 아니면 다음 concrete action 선택

이것이 /goal과 단순 반복 프롬프트의 차이입니다.


7. Budget limit: soft stop 설계

/goal에는 token budget 개념이 있습니다. 공개 migration에는 token_budget, tokens_used가 있고, runtime PR은 token budget exhaustion을 soft stop으로 처리한다고 설명합니다.

중요한 점은 예산 도달 시 active turn을 강제로 abort하지 않는다는 것입니다. 대신 goal을 budget_limited로 표시하고 wrap-up steering을 주입합니다.

budget_limit.md의 의도는 다음과 같습니다.

# 읽기 가이드: 아래 블록은 명령, 상태 흐름, 또는 템플릿 예시입니다.- active thread goal이 token budget에 도달했다.- objective는 user-provided data로 취급한다.- 새 실질 작업을 시작하지 않는다.- 진행 상황, 남은 작업, blocker, 다음 단계를 정리한다.- 실제 완료된 것이 아니라면 update_goal complete를 호출하지 않는다.

이건 좋은 설계입니다. 예산이 끝났다고 목표가 완료된 것은 아니기 때문입니다.

# 읽기 가이드: 아래 블록은 명령, 상태 흐름, 또는 템플릿 예시입니다.budget exhausted != goal complete

실무 agent에서 budget limit을 잘못 설계하면 두 가지 문제가 생깁니다.

잘못된 설계문제
예산 초과 시 즉시 hard abort사용자에게 남은 작업과 상태가 전달되지 않음
예산 초과를 complete로 처리미완료 작업이 완료처럼 보임

Codex의 방향은 그 중간입니다.

# 읽기 가이드: 아래 블록은 명령, 상태 흐름, 또는 템플릿 예시입니다.예산 초과→ budget_limited 상태 전이→ 새 작업 시작 금지→ 진행 요약과 남은 작업 보고→ complete는 실제 완료일 때만

8. Loop guard와 safety 장치

long-running goal에서 가장 위험한 것은 무한 반복입니다. /goal에는 이를 줄이기 위한 장치들이 들어가 있습니다.

8.1 No-tool continuation suppression

PR #18076은 continuation turn이 tool call 없이 끝나면 반복 automatic continuation을 suppress한다고 설명합니다.

의미는 이렇습니다.

# 읽기 가이드: 아래 블록은 명령, 상태 흐름, 또는 템플릿 예시입니다.continuation turn 시작→ 모델이 실제 파일 읽기/수정/명령 실행 없이 말만 함→ tool_calls == 0→ 다음 자동 continuation 억제

이 장치는 중요합니다. 그렇지 않으면 모델이 “계속 진행하겠습니다” 같은 말만 반복하는 루프에 빠질 수 있습니다.

8.2 Interrupt pause

사용자가 중단하면 active goal은 pause됩니다. 사용자가 멈췄는데도 goal이 계속 이어지는 것을 막기 위한 구조입니다.

# 읽기 가이드: 아래 블록은 명령, 상태 흐름, 또는 템플릿 예시입니다.사용자 interrupt→ active goal accounting→ goal status paused

8.3 Resume auto-reactivation

PR #18076 설명에 따르면 thread resume 시 plan mode가 아니면 paused goal을 자동 재활성화하는 동작이 들어갔습니다. 즉 중단과 재개를 goal lifecycle의 일부로 다룹니다.

8.4 Stale goal_id protection

상태 레이어에서는 goal_id 기반 stale update protection이 있습니다. 오래된 update가 새 goal을 덮어쓰지 못하게 막습니다.

8.5 Objective privilege separation

Continuation prompt는 objective를 “higher-priority instruction”이 아니라 user-provided data로 취급합니다. 사용자가 goal 안에 강한 명령을 넣더라도 system/developer instruction처럼 승격되지 않도록 하기 위한 구조입니다.


9. 나만의 Agent 설계에 적용하기

/goal에서 가장 배울 만한 점은 “자동 반복”을 runtime event로 분리한 것입니다.

나쁜 구현은 대개 이렇게 됩니다.

// 읽기 가이드: 실제 API가 아니라 구조를 설명하는 의사코드입니다.while (true) {  const result = await agent.run(goal)  if (result.done) break}

이 방식은 간단하지만 위험합니다.

# 읽기 가이드: 아래 블록은 명령, 상태 흐름, 또는 템플릿 예시입니다.- 완료 판정이 약하다.- 비용 제한이 부실하다.- 중단/재개가 어렵다.- 사용자 입력 우선순위를 다루기 어렵다.- 도구 호출 없는 반복을 막기 어렵다.- 이전 goal update가 새 goal을 덮어쓸 수 있다.

더 나은 구조는 이런 식입니다.

// 읽기 가이드: 실제 API가 아니라 구조를 설명하는 의사코드입니다.interface GoalRuntime {  state: GoalStateStore  scheduler: ContinuationScheduler  auditor: CompletionAuditor  accounting: UsageAccounting  controls: UserControls  guards: LoopGuards}

각 컴포넌트의 책임은 분리합니다.

컴포넌트책임
GoalStateStoreobjective, status, usage, timestamps 저장
ContinuationScheduleridle 상태에서만 다음 turn 시작
CompletionAuditor요구사항과 증거를 매핑해 완료 판단
UsageAccountingtoken/time budget 누적
UserControlspause, resume, clear, replace
LoopGuardsno-tool suppression, stale update protection, interrupt handling

실제 구현 의사코드는 다음처럼 잡을 수 있습니다.

// 읽기 가이드: 실제 API가 아니라 구조를 설명하는 의사코드입니다.async function maybeContinueIfIdle(session: Session) {  if (!session.isIdle()) return  if (session.hasPendingUserInput()) return   const goal = await goalStore.get(session.threadId)  if (!goal || goal.status !== "active") return  if (goalRuntime.isContinuationSuppressed(goal.goal_id)) return  if (goal.token_budget && goal.tokens_used >= goal.token_budget) return   await session.startContinuationTurn({    prompt: renderContinuationPrompt(goal),    goal_id: goal.goal_id,  })}

완료 판정도 별도 auditor로 분리하는 것이 좋습니다.

// 읽기 가이드: 실제 API가 아니라 구조를 설명하는 의사코드입니다.async function auditCompletion(goal: Goal, evidence: Evidence[]) {  const checklist = buildChecklist(goal.objective)  const coverage = mapEvidenceToChecklist(checklist, evidence)   if (coverage.hasMissingItems()) {    return { complete: false, nextAction: coverage.suggestNextAction() }  }   if (coverage.hasWeakVerification()) {    return { complete: false, nextAction: "collect stronger evidence" }  }   return { complete: true }}

핵심은 agent가 열심히 했는지가 아니라 요구사항이 실제 증거로 충족됐는지를 보는 것입니다.


10. 구현 체크리스트

나만의 goal 기반 agent를 만든다면 다음을 체크하는 것이 좋습니다.

# 읽기 가이드: 아래 블록은 명령, 상태 흐름, 또는 템플릿 예시입니다.Goal State[ ] goal_id를 둔다.[ ] objective를 저장한다.[ ] status를 active/paused/budget_limited/complete 등으로 제한한다.[ ] token/time usage를 누적한다.[ ] stale update protection을 둔다. Runtime[ ] turn started/finished 이벤트를 분리한다.[ ] tool completed 이벤트에서 usage를 집계한다.[ ] idle 상태에서만 continuation을 시작한다.[ ] 사용자 입력을 continuation보다 우선한다.[ ] interrupt 시 active goal을 pause한다.[ ] resume 시 goal 상태를 복원한다. Completion Audit[ ] objective를 success criteria로 재정리한다.[ ] 요구사항을 checklist로 만든다.[ ] 각 항목을 파일/명령/test 결과와 매핑한다.[ ] proxy signal만으로 완료 처리하지 않는다.[ ] 불확실하면 complete가 아니라 continue로 처리한다. Budget[ ] token budget을 둘 수 있다.[ ] budget 초과 시 complete로 처리하지 않는다.[ ] budget_limited 상태에서 wrap-up을 제공한다.[ ] 새 실질 작업을 시작하지 않도록 steering한다. User Controls[ ] pause를 지원한다.[ ] resume 또는 unpause를 지원한다.[ ] clear를 지원한다.[ ] replacement 시 기존 goal과 새 goal을 구분한다. Loop Guards[ ] tool call 없는 continuation은 반복하지 않는다.[ ] long-running command timeout을 둔다.[ ] 같은 실패를 반복하지 않도록 history를 기록한다.[ ] 권한과 writable scope를 제한한다.

11. 참고자료와 불확실성

참고자료

확인된 사실

  • thread_goals 테이블은 thread_id, goal_id, objective, status, token_budget, tokens_used, time_used_seconds, timestamp를 저장합니다.
  • statusactive, paused, budget_limited, complete로 제한됩니다.
  • app-server에는 thread/goal/get, thread/goal/set, thread/goal/clear RPC와 goal updated/cleared notification이 추가됐습니다.
  • model-facing tool은 get_goal, create_goal, update_goal이며, update_goal은 completion 중심으로 제한됩니다.
  • core runtime은 idle continuation, usage accounting, budget limit, interrupt pause, resume reactivation, no-tool suppression을 처리합니다.

작성자의 해석

  • /goal은 AI coding agent의 “목표 기반 runtime”을 대중 제품에 넣은 사례로 볼 수 있습니다.
  • 가장 중요한 설계 포인트는 continuation scheduler보다 completion audit입니다.
  • 이 구조는 Codex CLI뿐 아니라 자체 AI Agent, CI repair bot, long-running coding assistant에도 응용할 수 있습니다.

불확실성

  • 출시 직후 기능이라 CLI help, command alias, 문서 반영은 변경될 수 있습니다.
  • GitHub issue #19910에서 언급된 compaction failure mode는 사용자 보고 기준이며, 향후 수정될 수 있습니다.
  • 공개 소스 분석 기준이므로 내부 런타임 세부사항이나 제품 동작은 버전에 따라 달라질 수 있습니다.

마무리

정리하면, Codex CLI /goal은 단순한 slash command가 아니라 goal state를 중심으로 agent runtime을 구성한 기능입니다.

가장 중요한 교훈은 이겁니다.

# 읽기 가이드: 아래 블록은 명령, 상태 흐름, 또는 템플릿 예시입니다.AI Agent를 오래 돌리고 싶다면 while loop를 먼저 만들지 말고,상태, 이벤트, 감사, 예산, 사용자 제어를 먼저 설계해야 한다.

/goal은 그 방향을 잘 보여줍니다. 목표를 저장하고, runtime event로 이어가고, 실제 증거로 완료를 감사하고, budget과 interrupt를 상태 전이로 처리합니다.

AI coding agent를 직접 만들고 있다면 이 구조를 그대로 참고할 만합니다. 특히 Goal State + Evidence Checklist + Continuation Scheduler + Budget Stop + User Control 조합은 단순 반복보다 훨씬 안전한 출발점입니다.

Viewthread_goals, continuation runtime, and completion audit at the code level

In Part 1, we looked at Codex CLI/goalfrom the user's perspective. In this article, we look at the internal structure.

The key is simple.

# Reading Guide: The blocks below are examples of commands, state flows, or templates./goal is not a single command.It is a function that combines target state storage, app-server API, model tool, runtime continuation, and TUI control.

This article was written based on Codex GitHub PR and publicly available source files. This is a soon-to-be-released feature, so actual implementation may vary in future versions.

Analysis base date: 2026-05-02 Base version: Codex CLI0.128.0 Main reference materials: OpenAI Codex changelog, GitHub PR #18073–#18077,thread_goalsmigration,continuation.md,budget_limit.md


Key takeaways

  • /goalis a five-layer function leading to TUI command to app-server API to model tools to core runtime to state DB.
  • The goal status is stored in thethread_goalstable, and the status is limited toactive,paused,budget_limited, andcomplete.
  • The model tool cannot manipulate goals arbitrarily.update_goalis limited to completion processing, and pause/resume/clear/budget-limited transitions remain under user or runtime control.
  • The core runtime processes turn start, tool completion, turn finish, interrupt, resume, and idle continuation throughGoalRuntimeEvent.
  • The continuation prompt asks you to perform a completion audit based on the “current actual state” before completion.
  • From a good agent design perspective, the key to/goalis evidence event-driven continuation + audit + budget guard, notwhile true.

1. Overall structure: View in 5 layers

Based on the code,/goalis close to the structure below.

# Reading Guide: The blocks below are examples of commands, state flows, or templates.TUI /goal commandapp-server thread/goal APImodel tools: get_goal / create_goal / update_goalcore runtime: continuation / accounting / interrupt / resumestate DB: thread_goals table

Each layer has a different role.

layerrolekey points
TUIUI for users to create, stop and erase/goalCommand and status display
app-serverAPI where the client controls the thread goal stateget/set/clear, notification, resume snapshot
model toolsA tool that allows the model to view, create, and complete goalsPermission restrictions are important
core runtimeContinue, accounting, interrupt, resume processingCentral to creating real “keeps going”
state DBSave goal objective/status/usageThread-level persistence

Looking at this structure, it is clear that/goalis not simply a “prompt telling the model to continue.” The target state is in the DB, and the runtime updates the state according to the turn life cycle.


2. State DB:thread_goalstable

At the very bottom is thethread_goalstable. On a public migration basis, this table stores the following information:

columnmeaning
thread_idThread identifier with goal
goal_idIdentifier of the goal itself
objectiveUser-specified goals
statusOne ofactive,paused,budget_limited,complete
token_budgetOptional token budget
tokens_usedCumulative token usage during goal execution
time_used_secondsAccumulated time during goal execution
created_at_mscreation time
updated_at_msupdate time

If you write it as a pseudo type, you can see it like this.

// Reading Guide: This is not an actual API, but pseudocode that explains the structure.type ThreadGoal = {  thread_id: string  goal_id: string  objective: string  status: "active" | "paused" | "budget_limited" | "complete"  token_budget?: number  tokens_used: number  time_used_seconds: number  created_at_ms: number  updated_at_ms: number}

The important thing here isthread_id. A goal is not a simple memory flag, but is attached to thread state. So it can be connected to functions like resume, reconnect, and app-server snapshot.

Another important one isgoal_id. According to the description of PR #18073, stale update protection has been included. In other words, it is a device that prevents old goal updates from overwriting new goals.

# Reading Guide: The blocks below are examples of commands, state flows, or templates.problem:- Goal A is in progress.- The user replaces it with goal B.- The goal A update that arrives late overwrites the state of goal B. solve:- Check expected goal_id when updating.- If it is different from the current goal_id, it is considered a stale update and blocked.

This protection is important in AI agent runtime. This is because when multiple async tasks, tool results, and user mutations are mixed, “late-arriving updates” can break the state.


3. App-server API: thread goal control plane

The second layer is the app-server API. PR #18074 explains that the following RPC and notification were added to the v2 API.

# Reading Guide: The blocks below are examples of commands, state flows, or templates.RPC:- thread/goal/get- thread/goal/set- thread/goal/clear Notification:- thread/goal/updated- thread/goal/cleared

The reason this API is needed is because the client needs to reliably read and control the goal state.

API elementsrole
thread/goal/getCheck the goal status of the current thread
thread/goal/setSet goal or change state
thread/goal/clearremove goal
thread/goal/updatedNotify the client of goal changes
thread/goal/clearedNotify the client of goal deletion
resume/snapshot wiringAllows the reconnected client to view the current goal status.

With this layer, not only TUI but also other clients can see the same goal status. In other words,/goalis not a TUI-specific hack, but a structure that handles materialized thread goals through the app-server.


4. Model tools: Limited model permissions

The third layer is the model-facing tool. According to PR #18075, there are three goal-related tools:

# Reading Guide: The blocks below are examples of commands, state flows, or templates.get_goalcreate_goalupdate_goal

This is where the design gets interesting. The model does not allow unlimited manipulation of the goal.

ToolAllowed Roleslimits
get_goalCheck current goalread center
create_goalCreate an explicitly requested goalRestrict creation to only when there is no existing goal
update_goalGoal completion processingLimited to center on completion

The PR description explains that thepause,resume,clear, andbudget_limitedtransitions are not handled by the model at will, but are left user- or runtime-controlled.

This design is important.

Giving all state control to the model can cause problems like this.

# Reading Guide: The blocks below are examples of commands, state flows, or templates.- The model pauses itself to avoid work.- The model arbitrarily releases the budget exceeding state.- The model clears the goal created by the user.- Marked as complete even though it is not completed.

So/goalallows the model to perform tasks and declare completion, but separates user control from runtime control.

# Reading Guide: The blocks below are examples of commands, state flows, or templates.Model permissions: lookup, explicit creation, completion processingUser permissions: pause, resume/unpause, clear, replacementruntime permissions: budget_limited, accounting, continuation scheduling

This separation of rights is worth referring to when creating an agent system.


5. Core runtime: continuation state machine

The fourth layer is the most important. PR #18076 views long-running goals as a core runtime concern, not as a client. This is because the core manages turn lifecycle, tool completion boundaries, interruptions, resume behavior, and token usage.

Looking at thegoals.rsannotation in the public code, this module connects the core session and the state DB goal table and is responsible for goal mutation verification, protocol conversion, goal-update event issuance, and lifecycle hook.

Key events can be viewed as follows:

# Reading Guide: The blocks below are examples of commands, state flows, or templates.GoalRuntimeEvent- TurnStarted- ToolCompleted- ToolCompletedGoal- TurnFinished- MaybeContinueIfIdle- TaskAborted- ExternalMutationStarting- ExternalSet- ExternalClear- ThreadResumed

Summarized in pseudocode, it is as follows.

// Reading Guide: This is not an actual API, but pseudocode that explains the structure.on TurnStarted:  capture token usage baseline  if current thread has active goal:    mark goal active for this turn on ToolCompleted:  account token/time usage  reset no-tool continuation suppression  if token budget exceeded:    mark goal as budget_limited    inject budget wrap-up steering on TurnFinished:  account final usage  if this was a continuation turn and tool_calls == 0:    suppress next automatic continuation on MaybeContinueIfIdle:  if session is idle and active goal exists:    start continuation turn on TaskAborted with interrupt:  account usage  pause active goal on ThreadResumed:  reactivate paused goal outside plan mode

Here, the true nature of/goalis revealed. The reason Codex “appears to continue working” is not because the model runs in an infinite loop by itself, but because it schedules a continuation turn while the core runtime is idle.

# Reading Guide: The blocks below are examples of commands, state flows, or templates.active goal exists+ session is idle+ not suppressed+ budget not exhausted= start continuation turn

6. Continuation prompt: The key to completion auditing

continuation.mdtemplate is the key to/goalquality.

This prompt instructs you to continue executing the active thread goal first. At the same time, it specifies that the objective should be treated as “user-provided data.” In other words, the goal statement is not promoted like a system instruction.

Also, the following information is included in each continuation.

# Reading Guide: The blocks below are examples of commands, state flows, or templates.Time spent pursuing goalTokens usedtoken budgetTokens remaining

The most important part is the completion audit. The prompt asks you to do the following before declaring completion:

requestmeaning
Reorganize objectives into concrete deliverables/success criteriaConvert your goals into testable form
Mapping all explicit requirements to evidence checklistAvoid missing requirements
View real evidence including files, command output, test results, PR status, etc.Judge based on current status, not words
Do not complete with proxy signal alone“Passing the test” is only evidence if it covers the entire goal
If you are uncertain, keep working instead of completing.Prevent premature completion in ambiguous states

This part is very important in AI agent design.

This is how a bad agent loop ends:

# Reading Guide: The blocks below are examples of commands, state flows, or templates.One test passedto It's probably okay→ complete

A good goal runtime should end like this.

# Reading Guide: The blocks below are examples of commands, state flows, or templates.List your target requirementsto map each requirement to actual evidenceto Check missing/unverified itemsto complete if all are metto or select the next concrete action

This is the difference between/goaland a simple repeat prompt.


7. Budget limit: soft stop design

/goalhas the concept of token budget. Public migrations includetoken_budgetandtokens_used, and runtime PR explains that token budget exhaustion is treated as a soft stop.

The important thing is that active turns are not forced to abort when the budget is reached. Instead, we mark the goal asbudget_limitedand inject wrap-up steering.

The intention ofbudget_limit.mdis as follows:

# Reading Guide: The blocks below are examples of commands, state flows, or templates.- The active thread goal has reached the token budget.- Objective is treated as user-provided data.-Do not start new substantive work.- Organize progress, remaining tasks, blockers, and next steps.- Do not call update_goal complete unless it is actually completed.

This is a good design. Just because the budget is over doesn't mean the goal is complete.

# Reading Guide: The blocks below are examples of commands, state flows, or templates.budget exhausted!= goal complete

If the budget limit is designed incorrectly in a practical agent, two problems arise.

bad designproblem
Immediate hard abort when budget is exceededRemaining tasks and status are not communicated to users
Treat budget exceedance as completeUnfinished tasks appear complete

Codex's direction is somewhere in between.

# Reading Guide: The blocks below are examples of commands, state flows, or templates.over budgetto budget_limited state transitionto prevent starting new tasksto Summary of progress and reporting of remaining workto complete only when it is actually completed

8. Loop guard and safety device

The most dangerous thing about long-running goals is endless repetition./goalcontains devices to reduce this.

8.1 No-tool continuation suppression

PR #18076 explains that automatic continuations are suppressed when the continuation turn ends without a tool call.

The meaning is this:

# Reading Guide: The blocks below are examples of commands, state flows, or templates.Start continuation turnThe to model just talks without actually reading/editing files/executing commands.→ tool_calls == 0to suppress next automatic continuation

This device is important. Otherwise, your model can get stuck in a loop where it just says things like “I’ll keep going.”

8.2 Interrupt pause

When the user stops, the active goal is paused. This is a structure to prevent the goal from continuing even if the user stops.

# Reading Guide: The blocks below are examples of commands, state flows, or templates.user interrupt→ active goal accounting→ goal status paused

8.3 Resume auto-reactivation

According to the description of PR #18076, when thread resumes, an action has been taken to automatically reactivate paused goals if they are not in plan mode. In other words, it treats interruption and resumption as part of the goal lifecycle.

8.4 Stale goal_id protection

In the state layer, there is stale update protection based ongoal_id. Prevents old updates from overwriting new goals.

8.5 Objective privilege separation

The continuation prompt treats the objective as user-provided data rather than a “higher-priority instruction”. This is a structure to prevent it from being promoted to a system/developer instruction even if the user enters a strong command in the goal.


9. Apply to your own Agent design

The most important thing to learn from/goalis the separation of “auto-repeat” into runtime events.

Bad implementations usually end up like this.

// Reading Guide: This is not an actual API, but pseudocode that explains the structure.while (true) {  const result = await agent.run(goal)  if (result.done) break}

This method is simple but risky.

# Reading Guide: The blocks below are examples of commands, state flows, or templates.- The completion judgment is weak.- Cost restrictions are poor.- Difficult to stop/resume.- Difficult to handle user input priorities.- It is difficult to prevent repetition without tool calls.- A previous goal update may overwrite the new goal.

A better structure would be like this:

// Reading Guide: This is not an actual API, but pseudocode that explains the structure.interface GoalRuntime {  state: GoalStateStore  scheduler: ContinuationScheduler  auditor: CompletionAuditor  accounting: UsageAccounting  controls: UserControls  guards: LoopGuards}

The responsibilities of each component are separated.

componentresponsibility
GoalStateStoreSave objective, status, usage, timestamps
ContinuationSchedulerNext turn starts only in idle state
CompletionAuditorMapping requirements and evidence to determine completion
UsageAccountingtoken/time budget accumulation
UserControlspause, resume, clear, replace
LoopGuardsno-tool suppression, stale update protection, interrupt handling

The actual implementation pseudocode can be captured as follows.

// Reading Guide: This is not an actual API, but pseudocode that explains the structure.async function maybeContinueIfIdle(session: Session) {  if (!session.isIdle()) return  if (session.hasPendingUserInput()) return   const goal = await goalStore.get(session.threadId)  if (!goal || goal.status !== "active") return  if (goalRuntime.isContinuationSuppressed(goal.goal_id)) return  if (goal.token_budget && goal.tokens_used >= goal.token_budget) return   await session.startContinuationTurn({    prompt: renderContinuationPrompt(goal),    goal_id: goal.goal_id,  })}

It is recommended that completion judgments be separated by a separate auditor.

// Reading Guide: This is not an actual API, but pseudocode that explains the structure.async function auditCompletion(goal: Goal, evidence: Evidence[]) {  const checklist = buildChecklist(goal.objective)  const coverage = mapEvidenceToChecklist(checklist, evidence)   if (coverage.hasMissingItems()) {    return { complete: false, nextAction: coverage.suggestNextAction() }  }   if (coverage.hasWeakVerification()) {    return { complete: false, nextAction: "collect stronger evidence" }  }   return { complete: true }}

The key is not whether the agent worked hard, but whether the requirements were met with actual evidence.


10. Implementation Checklist

If you are creating your own goal-based agent, it is recommended to check the following.

# Reading Guide: The blocks below are examples of commands, state flows, or templates.Goal State[ ] Place goal_id.[ ] Save the objective.[ ] Limit status to active/paused/budget_limited/complete, etc.[ ] Accumulate token/time usage.[ ] Enable stale update protection. Runtime[ ] separates the turn started/finished events.[ ] Count usage from tool completed events.[ ] The continuation starts only in idle state.[ ] User input takes precedence over continuation.[ ] Pauses the active goal when interrupted.[ ] Restores the goal state when resumed. Completion Audit[ ] Reorganize objectives into success criteria.[ ] Make requirements into a checklist.[ ] Map each item to a file/command/test result.[ ] Do not complete processing with proxy signal alone.[ ] If uncertain, proceed with continue rather than complete. Budget[ ] A token budget can be set.[ ] If the budget is exceeded, it is not processed as complete.[ ] Provides wrap-up in budget_limited state.[ ] Steering so as not to start a new substantive task. User Controls[ ] pause is supported.[ ] Supports resume or unpause.[ ] Clear is supported.[ ] When replacing, distinguish between the existing goal and the new goal. Loop Guards[ ] A continuation without a tool call is not repeated.[ ] Set a long-running command timeout.[ ] Record history to avoid repeating the same failure.[ ] Limit permissions and writable scope.

11. References and uncertainty

References

confirmed facts

  • Thethread_goalstable storesthread_id,goal_id,objective,status,token_budget,tokens_used,time_used_seconds, timestamps.
  • statusis limited toactive,paused,budget_limited,complete.
  • thread/goal/get,thread/goal/set,thread/goal/clearRPC and goal updated/cleared notification have been added to app-server.
  • The model-facing tools areget_goal,create_goal, andupdate_goal, andupdate_goalis limited to the center of completion.
  • The core runtime handles idle continuation, usage accounting, budget limit, interrupt pause, resume reactivation, and no-tool suppression.

Author's interpretation

  • /goalcan be seen as an example of incorporating the “goal-based runtime” of an AI coding agent into a popular product.
  • The most important design point is the completion audit rather than the continuation scheduler.
  • This structure can be applied not only to Codex CLI but also to its own AI Agent, CI repair bot, and long-running coding assistant.

uncertainty

  • As this is a feature immediately after release, CLI help, command alias, and documentation may be subject to change.
  • The compaction failure mode mentioned in GitHub issue #19910 is based on user reports and may be modified in the future.
  • This is based on open source analysis, so internal runtime details or product behavior may vary across versions.

finish

In summary, Codex CLI/goalis not a simple slash command, but a function that configures the agent runtime around the goal state.

The most important lesson is this:

# Reading Guide: The blocks below are examples of commands, state flows, or templates.If you want to run the AI ​​Agent for a long time, do not create a while loop first,Status, events, auditing, budget, and user controls must be designed first.

/goalshows that direction well. It stores goals, continues with runtime events, audits completion with actual evidence, and handles budgets and interrupts as state transitions.

If you are creating your own AI coding agent, this structure is worth referring to. In particular, theGoal State + Evidence Checklist + Continuation Scheduler + Budget Stop + User Controlcombination is a much safer starting point than simple repetition.

댓글

GitHub 계정으로 로그인하면 댓글을 남길 수 있습니다. 댓글은 GitHub Discussions를 통해 운영됩니다.

TOP