Skip to content

Resume unfinished tasks from saved trajectory checkpoints #42

Closed

Description

@vicgupta

Summary

Add an explicit --resume <trajectory.json> mode so developers and automation can continue an unfinished task from a validated local checkpoint, retaining conversation context and usage accounting. Keep the single-binary, noninteractive workflow: no session service, database, or interactive picker.

This is a proposal based on an observed capability gap and established comparable workflows, not a claim of demonstrated demand from tinyagent users. Flag names and checkpoint representation below are proposed public-interface choices for maintainer review.

Problem and opportunity

Today -o saves a trajectory after tool turns and at termination, but the CLI requires a task and Agent.Run always constructs a new history. A run stopped by a step/cost/time limit, interruption, or provider error can leave useful edits in the workspace and useful observations in JSON, with no supported way to continue that conversation. Starting again with the same task does not restore that context.

Resume would make the existing limits and saved history more useful: inspect the workspace, resolve the interruption or deliberately increase a limit, then continue the same task. This is particularly relevant alongside the recently shipped run accounting and the proposed long-run compaction work. It does not guarantee less spending or successful task completion.

Research and evidence

Verified repository behavior: inspected the checkout on 2026-10-24 and refreshed findings against main at ffe3e045e4fa2d7c150fdbce8fa2f975ddda6864 before publication. The intervening change was the pricing warning in PR #40; it does not add continuation. Source links below pin that refreshed commit.

  • Agent.Run initializes system/task messages, queries the provider with history, executes tool calls sequentially, and saves via OnStep after the tool batch. It also saves on normal/error/limit termination. It has no continuation entry point.
  • Trajectory already contains task, model, messages, steps, cost, token/cache totals, and exit status. Save uses a temporary file and rename; the format has no schema version or working-directory identity. These are useful foundations, not yet a sufficient recovery contract.
  • run() requires --task, constructs a fresh provider/executor, and wires -o only to saving. Issue #15 and merged PR #16 establish the existing accounting/summary workflow.
  • Issue #24 and open PR #28 address context compaction, not restarting a process. PR Compact the conversation when it nears the model's context window #28 proposes a compacted model view separate from the full transcript; restoring only messages would therefore be insufficient if that work lands.

External findings, checked 2026-10-24; living documentation unless a date is stated:

  • Pi's session documentation documents continuing sessions grouped by working directory and opening a known session by path/ID. Aider's options reference documents opt-in restoration of previous chat messages. These demonstrate practical continuation interfaces; tinyagent can use an explicit file without adopting their broader interactive interfaces.
  • OpenCode's CLI documentation documents continuation for noninteractive run. This supports script-oriented continuation as a concrete workflow, rather than requiring a TUI.
  • OpenCode issue #19023, opened 2026-03-24, reports orphaned tool state after interruption/restart. It was automatically closed for inactivity on 2026-07-03, not verified fixed. This is a firsthand report from another project, not evidence of a tinyagent defect or its prevalence. It motivates explicit checkpoint boundaries and refusing ambiguous tool state.

Interpretation: continuation has a close architectural fit because tinyagent already persists its linear conversation and totals. Its value here is a small, inspectable CLI contract; it is not novel relative to competitors. External precedent supports the opportunity, but adoption and frequency of interrupted tinyagent runs remain unknown.

Users and use cases

  • A developer reaches a step limit, inspects the current changes, and deliberately raises the cumulative ceiling to continue.
  • An operator fixes credentials/connectivity after a provider failure, or restarts after Ctrl-C, retaining the last usable checkpoint.
  • A script supplies explicit input/output paths and receives the existing success/failure exit behavior and stderr summary.

Goals

  • Continue the same unfinished task and supported model from a validated checkpoint.
  • Preserve recorded history and accounting without executing historical tool calls.
  • Make checkpoint compatibility, persistence failures, and recovery limitations observable.

Non-goals

  • An interactive chat/session browser, new-task follow-ups, branching UI, or model/provider switching.
  • Restoring files, Git state, shell environment, live processes, external services, or credentials.
  • Arbitrary instruction changes, automatic migration of ambiguous legacy files, or exactly-once execution across crashes.
  • Implementing compaction, background tools, tool approvals, or OS sandboxing as part of this feature.

Proposed behavior

Example interface:

# After this run stops at its step limit:
tinyagent -t "fix the failing test" --cwd ~/src/project --step-limit 20 -o run.json

# Continue the same task, allowing up to 40 total model steps:
tinyagent --resume run.json --cwd ~/src/project --step-limit 40 -o continued.json
  1. Checkpoint eligibility. Add versioned resume metadata to newly written trajectories, including the execution root and enough instruction/tool compatibility information to validate continuation. A supported unfinished checkpoint may have an in-progress status or a limit/interruption/error status. Reject Submitted/Completed artifacts, unsupported versions, and pre-feature files lacking required metadata, with an explanation; do not guess missing state.
  2. Explicit inputs. Resume uses the saved task and model. Reject combining --resume with --task, and reject an explicit different model; the normal default model/environment must not silently override the saved model. Require explicit --cwd matching the recorded canonical root and a distinct -o destination. Resolve path aliases sufficiently to prevent overwriting the input through a symlink/hard link. Preserve the source checkpoint and refuse to overwrite an existing destination on startup.
  3. Instructions and configuration. Retain the saved system prompt. Reconstruct the effective prompt using current config and the recorded AGENTS.md-loading mode; refuse continuation if it differs, explaining that a fresh task is needed. Do not silently execute with changed instructions or duplicate AGENTS.md. Runtime limits/tool timeout/output settings use the existing config/flag precedence; credentials and endpoints come from current normal provider setup, never from checkpoint data.
  4. Continuation. Validate history before provider setup or execution: system/task structure, supported roles, finite/nonnegative counters, and complete assistant/tool-result pairing at a model-query boundary. Tool IDs must be matched within their assistant turn, not assumed globally unique. Reject partial/malformed turns without repairing them by replay. The next action is a new model query with restored context; never dispatch a tool merely because its call appears in the file.
  5. Accounting. Preserve cumulative steps, cost, input/output, and cache totals. Step/cost limits remain cumulative ceilings: an already exhausted ceiling makes no new request. Users increase the ceiling explicitly to allow more work. Wall time and the reported elapsed duration apply to the new invocation; stopped time is not charged. The new invocation clears the active terminal status/submission while retaining the previous termination information as resume provenance.
  6. Persistence and feedback. Write the validated starting state to the new destination before the first request, then checkpoint after completed turns and at termination. In resume mode a save failure stops further queries/tools with a nonzero exit and stderr diagnostic; preserve the last valid file. Report the resume boundary/previous status on stderr without echoing transcript content. Existing fresh-run output and exit conventions remain compatible.
  7. Recovery boundary. Add a continuation notice to the model and a concise stderr notice that workspace state may have changed and commands may have produced side effects after the last save. A checkpoint is conversation state, not a filesystem transaction. A hard crash during a tool batch can leave unrecorded effects even when the previous checkpoint is valid. Require inspection/revalidation of current state in the documented workflow; make no automatic rollback or exactly-once claim.

Acceptance criteria

  • Given a new-format checkpoint stopped after a tool turn at step 20, resuming with ceiling 40 sends the saved context plus the documented continuation notice to the next model query. Previously completed tool calls are not dispatched again by the harness.
  • Given multiple calls in one assistant turn, every result is restored in order; repeated IDs in separate turns are handled correctly. Missing, duplicate, or orphaned results are rejected before provider setup or tool execution.
  • Missing/unreadable/empty/malformed files, unsupported schema versions, missing resume metadata, invalid counters, terminal-success artifacts, and incompatible history yield a nonzero exit and actionable stderr diagnostic without exposing the transcript or modifying the source.
  • Missing/mismatched explicit root, changed effective instructions/tool compatibility, a conflicting task/model, and a source/destination alias are rejected before provider setup. Without an explicit model flag, the saved model wins over normal model defaults.
  • Restored accounting plus newly returned usage appears in the output trajectory and summary. An exhausted cumulative step/cost ceiling makes zero model calls; raising it permits continuation. Wall time restarts for this invocation and remains cancellable.
  • The source stays byte-identical. A new destination is persisted before work; a preexisting destination is refused. Injected initial/turn-save failures stop further work and leave the prior valid checkpoint readable. A subsequent interrupted invocation can resume from its supported saved boundary.
  • If compaction metadata from Compact the conversation when it nears the model's context window #28 is supported, restore its effective model view as well as full audit history. Otherwise reject that checkpoint explicitly before any request; never silently expand or discard the compacted state.
  • No shell/process/file rollback or historical tool execution occurs on load. Resume diagnostics and the model notice describe stale workspace and unrecorded-side-effect risks. New metadata excludes credentials/environment dumps; new checkpoint/temp files are private to the current user where supported.
  • Fresh runs retain existing behavior and existing top-level trajectory fields/types. Existing stdout/stderr conventions, streaming and nonstreaming modes, provider selection, and success/failure exit codes remain compatible.
  • Help and README document the flags, example, eligibility, limits, source preservation, instruction checks, privacy, and crash boundary. Focused tests and the repository's build/vet/test checks pass on its declared Go toolchain.

Technical context and constraints

Repository facts: the project is a static Go CLI; go.mod declares Go 1.27.1 and YAML v3 as its direct external module. The Makefile targets Linux/macOS/Windows on amd64/arm64. internal/model/provider.go defines the common Model.Query, Message, and usage types; OpenRouter/Ollama use the OpenAI-shaped adapter, while Anthropic and Codex translate history. APIs live under internal; the externally observable interfaces here are CLI, YAML, trajectory JSON, and provider wire requests.

Relevant boundaries are cmd/tinyagent/main.go (validation/provider setup/output), internal/agent/loop.go (limits, instructions, query boundary), internal/trajectory/trajectory.go (validation/serialization), and existing model adapters/tests. Current OnStep has no error return and ordinary saves only warn; reliable resume-mode persistence needs an explicit failure path. Current rename-based saving should not be advertised as power-loss durability without further guarantees.

Proposed choices: versioned additive metadata, matching-root/instruction checks, and a distinct output artifact keep initial scope conservative. Maintainers should review those CLI/format choices. No service, database, new provider protocol, or framework dependency is required by this proposal. Provider wire validity must be verified rather than inferred solely from JSON round-tripping.

Alternatives considered

Major feature candidate Value/evidence and fit Trade-off / decision
Resume checkpoints (selected) Direct gap in saved-history/limit workflows; continuation is documented in several comparable agents. Moderate state/compatibility work, bounded to the existing loop and format; smaller ongoing surface than a new integration subsystem. No tinyagent demand measurement.
Automatic context compaction Strong fit for growing history. Already covered by #24 and open PR #28; rejected as duplicate work.
Tool permission / analysis mode README documents unsandboxed bash and lexical file boundaries; OpenCode permissions show established tool policy controls. Useful separate capability, but policy/UX semantics and symlink/shell escape risks require their own security scope. Tool denial alone must not be sold as isolation.
MCP external tool integration OpenCode's MCP documentation demonstrates external-tool workflows and explicitly notes added context usage. Broader process/transport/authentication/schema lifecycle and maintenance burden; no repository-specific external-tool use case found to justify it over continuation.
Background command sessions Fits server/watch workflows missing from synchronous bash. Already proposed by newly opened #41; rejected as duplicate work.

Within resume, directly loading legacy messages is simpler but cannot verify root/compatibility or restore a compacted model view. A session database/picker adds discovery and storage policies outside the requested capability. The explicit-file approach is the recommended initial slice.

Cross-cutting considerations

  • Security/privacy: checkpoints contain code, prompts and tool outputs and must be treated as trusted local execution inputs. Do not read paths or credentials from arbitrary metadata, upload artifacts, or print contents on parse failure. Parsing should have a documented size bound and reject unsupported executable/tool state. Create checkpoint/temp files privately and without following a preexisting temporary-file symlink; current Save uses mode 0644 and a predictable temporary path.
  • Reliability/performance: validation is local and bounded by checkpoint size. Resume adds no model request of its own; the next ordinary request still incurs normal context/token cost. Preserve a complete turn boundary and stop on persistence failure. This does not solve context overflow.
  • Compatibility/migration: additive fields retain existing JSON consumers' known fields. Legacy trajectories remain inspectable but initially non-resumable. Reject unknown resume formats rather than destructive migration. Rolling back the binary leaves the untouched input artifact available; it does not undo workspace edits.
  • Accessibility/supportability: keep a noninteractive plain-text CLI with no color-only state or new terminal UI. Diagnostics should identify the failed validation category without dumping content. Resume provenance must make the input checkpoint and previous termination distinguishable from the active result.
  • Maintenance: keep validation and compatibility rules explicit and fixture-tested. No maintainer/owner assignment is proposed.

Test and verification expectations

Extend scripted-model tests in internal/agent/loop_test.go and CLI tests in cmd/tinyagent/main_test.go; add trajectory fixtures and persistence fault injection. Cover valid resume, every refusal category above, interrupted writes, same-file aliases, exhausted/increased ceilings, repeated per-turn IDs, and no historical-tool dispatch.

Use existing local HTTP/SSE stubs to verify restored histories through OpenAI-compatible, Anthropic, and Codex adapters, streamed/nonstreamed as supported; no live credentials are needed. Include compaction fixtures if that format is supported. Exercise filesystem/path behavior on supported OSes. Run go build ./..., go vet ./..., and go test ./... on the declared toolchain. These are expectations, not test results from this research task.

Documentation and rollout considerations

Document the versioned checkpoint contract and one stop/inspect/increase-limit/resume example. Explain that old trajectories remain logs, successful runs cannot be extended in this initial scope, instructions/root must match, input artifacts are preserved, and neither process state nor unsaved effects are recovered.

Roll out as an opt-in CLI mode with additive metadata on newly saved trajectories; no automatic session discovery or separate feature flag is needed. Existing invocations continue normally; tasks that change AGENTS.md or other effective instructions will need a fresh task under the initial matching-instructions policy. Verify rejection diagnostics and provider compatibility before release; unsupported checkpoint versions must remain non-destructive.

Dependencies and related work

  • #15 / PR #16: shipped accounting, which continuation must retain.
  • #24 / PR #28: coordinate model-view serialization; open work, not an existing capability on the inspected commit.
  • #41: proposed process registry; persisted process handles must never imply that a new tinyagent process can reattach to those children.
  • v0.3.0, published 2026-10-24: current release context. External projects above are research references, not proposed dependencies.

Duplicate check: reviewed the then-listed open/closed issues and PRs and relevant bodies, plus title/body searches for resume/checkpoint/restart/persistence/session/continuation/recover/replay/restore/interrupted/trajectory. No equivalent proposal was found. Discussions are disabled; the inspected tree has no roadmap/RFC/ADR, CONTRIBUTING, AGENTS.md, or issue template. No prior rejection of this capability was found.

Open questions

  • Should the first release support Compact the conversation when it nears the model's context window #28's compacted checkpoint representation immediately, or explicitly refuse compacted artifacts until that representation is stable? Both preserve the required refusal/validation contract.
  • Is additive resume metadata in the existing trajectory format preferable to a separate checkpoint envelope? Keep the explicit-file workflow, audit history, and compatibility rules whichever representation is chosen.

Activity

  1. added
    enhancementNew feature or request
    amf:readyReady for amf to turn into a pull request
    amf:failedamf could not process this issue; see its comment
    and removed
    amf:readyReady for amf to turn into a pull request
    on Oct 24, 2026
  2. vicgupta commented on Oct 24, 2026

    @vicgupta
    OwnerAuthor

    amf could not turn this issue into a pull request:

    opencode: exit status 1 (log: ~/amf-runner/tinyagent/.amf/logs/issue-42.log)
    
  3. added
    amf:readyReady for amf to turn into a pull request
    amf:failedamf could not process this issue; see its comment
    and removed
    amf:failedamf could not process this issue; see its comment
    amf:readyReady for amf to turn into a pull request
    on Oct 24, 2026
  4. vicgupta commented on Oct 24, 2026

    @vicgupta
    OwnerAuthor

    amf could not turn this issue into a pull request:

    opencode: exit status 130 (log: ~/amf-runner/tinyagent/.amf/logs/issue-42.log)
    
  5. added
    amf:doneamf opened a pull request for this issue
    and removed
    amf:failedamf could not process this issue; see its comment
    on Oct 24, 2026
  6. vicgupta commented on Oct 24, 2026

    @vicgupta
    OwnerAuthor

    amf opened #54 for this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    amf:doneamf opened a pull request for this issueenhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions