mirror of
https://github.com/agno-agi/agno.git
synced 2026-10-12 02:10:54 +00:00
## Summary Adds step replay to `ClaudeAgent` using the same API as native `Agent.continue_run`. Stacked on #10905 (`feat/harness-agents-phase2-astra`); it needs #10904's database-backed Claude SDK transcript store. - **`ClaudeAgent.continue_run` / `acontinue_run`**: accept `continue_from` (`"end"`, `"last_user"` or a message index), `fork` and `input`, and support `stream=True` and `background=True`. Continuing forks the stored SDK transcript at the chosen message (`fork_session_via_store(..., up_to_message_id=...)`) and resumes the fork, so the model only remembers what happened up to that point. - `fork=True` writes a sibling run with `forked_from_run_id` / `forked_from_message_index`; `fork=False` replaces the source run in place and keeps its fork lineage. - `continue_from="last_user"` without `input` replays the whole turn: it forks just before the prompt (or starts a fresh SDK session for the session's first turn) and re-sends the original input. - A mid-turn continue without `input` sends "Continue from where you left off." - Later turns in the session continue from the replayed branch, because the session's SDK pointer moves to the fork. - **Transcript positions on runs**: the adapter enables the SDK's `replay-user-messages` so the prompt arrives with its transcript uuid. It records the SDK session id and uuid for each top-level prompt, tool call, tool result and final reply in `Message.provider_data["claude_sdk"]`. Tool results are marked as checkpoints, so `GET /agents/{id}/runs/{run_id}/checkpoints` lists each step. - **AgentOS**: no router changes. `/continue` and `/checkpoints` already dispatch on `acontinue_run` / `aget_run_output`, so `ClaudeAgent` moves from 501 to supported. Unsupported options (`regenerate`, `replace_original`, `additional_instructions`, HITL `tools`) return 400. - **`BaseExternalAgent`**: generic plumbing only. `ExternalContinuation` carries the kept transcript into `_arun_non_stream` / `_arun_stream`, a per-run `run_state` dict reaches the adapter, and an `_annotate_run_output` hook (no-op by default) lets an adapter attach per-message data. Other adapters are unaffected: none forwards run kwargs to its framework. - **Resume fallback unchanged for normal runs**: the echoed prompt is not counted as a received message, so #10903's "stored session cannot be resumed, start fresh with history" fallback still works. Continuations never fall back; a failed fork resume errors instead of silently replaying the full history. ## Type of change - [ ] Bug fix - [x] New feature - [ ] Breaking change - [ ] Improvement - [ ] Model update - [ ] Other: --- ## Checklist - [x] Code complies with style guidelines - [x] Ran format/validation scripts (`./scripts/format.sh` and `./scripts/validate.sh`) - [x] Self-review completed - [x] Documentation updated (comments, docstrings) - [x] Examples and guides: Relevant cookbook examples have been included or updated (if applicable) - [x] Tested in clean environment - [x] Tests added/updated (if applicable) ### Duplicate and AI-Generated PR Check - [x] I have searched existing [open pull requests](https://github.com/agno-agi/agno/pulls) and confirmed that no other PR already addresses this issue - [ ] If a similar PR exists, I have explained below why this PR is a better approach - [x] Check if this PR was entirely AI-generated (by Copilot, Claude Code, Cursor, etc.) --- ## Additional Notes Base is `feat/harness-agents-phase2-astra` (#10905), not `main`. Merge after #10903, #10904 and #10905. Limits: - Only runs recorded with transcript storage (PostgresDb, AsyncPostgresDb, SqliteDb, AsyncSqliteDb) can be continued; older runs and other databases raise a clear error. - Files and other side effects after the checkpoint are not rewound. The SDK's file checkpointing does not carry over to forked sessions. - Steps inside subagents (`parent_tool_use_id`) are not checkpoints; they live in subagent transcripts. - `regenerate` / `replace_original` and Codex are follow-ups. Verification: - Confirmed against the real SDK (0.2.95) that streamed message uuids equal stored transcript uuids, and that forks cut at a tool result or before the prompt only remember up to that point. - Live end-to-end on SQLite: fork from a tool result, replay of a first and a later turn, in-place streamed continue, follow-up turn on the branch, and AgentOS `/checkpoints` + `/continue` (non-stream and SSE). `cookbook/frameworks/claude-agent-sdk/continue_from.py` passes with `claude-sonnet-4-6`. - New unit tests against the fake SDK: transcript positions and checkpoints (stream and non-stream), fork from a tool result, in-place continue lineage (sync API), turn replay with and without a parent entry, no fallback on a failed continuation, rejected options, and prompt echo not blocking the resume fallback. Each guard was mutation-checked: breaking lineage, allowing fallback, or counting the echo as received makes a test fail. - `validate.sh`: no ruff or mypy findings in touched files; the remaining mypy errors are pre-existing model/MCP SDK typing issues from local dependency versions. Postgres integration tests were not run locally. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Ashpreet <[email protected]> Co-authored-by: Ashpreet <[email protected]> Co-authored-by: kausmeows <[email protected]> Co-authored-by: Claude Fable 5.1 <[email protected]>
47 lines
1.2 KiB
Python
47 lines
1.2 KiB
Python
"""
|
|
AgentOS File System
|
|
===================
|
|
|
|
Enable a private durable filesystem with ``filesystem=True``. By default files
|
|
are scoped to the agent. AgentOS adds user scope only when user isolation is on.
|
|
|
|
Prerequisites: OPENAI_API_KEY is needed only for agent runs
|
|
Run: .venvs/demo/bin/python cookbook/05_agent_os/27_filesystem/basic.py
|
|
Try: Connect Agno OS to http://localhost:7777 and open File System
|
|
"""
|
|
|
|
from os import getenv
|
|
|
|
from agno.agent import Agent
|
|
from agno.db.postgres import PostgresDb
|
|
from agno.models.openai import OpenAIResponses
|
|
from agno.os import AgentOS
|
|
|
|
db = PostgresDb(
|
|
id="agentos-knowledge-postgres",
|
|
db_url=getenv("DATABASE_URL", "postgresql+psycopg://ai:ai@localhost:5532/ai"),
|
|
)
|
|
|
|
|
|
filesystem_agent = Agent(
|
|
id="filesystem-agent",
|
|
name="File System Agent",
|
|
model=OpenAIResponses(id="gpt-5.6-luna"),
|
|
db=db,
|
|
filesystem=True,
|
|
instructions="Keep durable working notes in your filesystem.",
|
|
markdown=True,
|
|
debug_mode=True,
|
|
)
|
|
|
|
agent_os = AgentOS(
|
|
id="filesystem-os",
|
|
description="AgentOS with a durable per-agent filesystem.",
|
|
db=db,
|
|
agents=[filesystem_agent],
|
|
)
|
|
app = agent_os.get_app()
|
|
|
|
if __name__ == "__main__":
|
|
agent_os.serve(app="basic:app", reload=True)
|