mirror of
https://github.com/langchain-ai/deepagents.git
synced 2026-07-23 02:05:44 -04:00
564e5a05bc
`/offload` now stores archived conversation history through the agent's backend. --- `/offload` previously summarized and saved conversation history in the client process. In server and sandbox modes, that process does not own the backend used by the agent: persistence could fail against a read-only filesystem, and even a successfully written archive would not be available to the agent through `read_file`. This changes Deep Agents Code to run the existing `compact_conversation` tool through the active agent instead. The command seeds a tool call into the thread, approves the expected human-in-the-loop interrupt because the user explicitly requested `/offload`, resumes the graph, and reads the persisted summarization event back from server state. The archive is therefore written through the agent's composite backend and remains readable by the agent in local, server, and sandbox runs. The old client-side `perform_offload` helper (and its `OffloadResult` / `OffloadThresholdNotMet` / `OffloadModelError` result types) is removed, as summarization and persistence now run through the agent. In local mode, the `conversation_history` backend now roots under `~/.deepagents` (via `_offload_fallback_root`, with a hardened private-temp fallback when the home directory is not writable) instead of a throwaway `tempfile.mkdtemp` directory, so offloaded history persists across sessions. The SDK's `compact_conversation` API is unchanged; this PR is confined to Deep Agents Code. Made by [Open SWE](https://openswe.vercel.app/agents/1cbc308e-b411-2a09-bd6b-541e606ca4c5) --------- Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
116 lines
4.1 KiB
Python
116 lines
4.1 KiB
Python
"""Lightweight runtime context types for the CLI agent graph.
|
|
|
|
Carries per-run overrides (model swap/params, approval mode) passed via
|
|
`context=`. Extracted from `configurable_model` so hot-path modules (`app`,
|
|
`textual_adapter`) can import `CLIContext` without pulling in the langchain
|
|
middleware stack.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass, field
|
|
from typing import Any, TypedDict
|
|
|
|
|
|
@dataclass
|
|
class CLIContextSchema:
|
|
"""Declared `context_schema` for the agent graph.
|
|
|
|
Registered via `context_schema=` when the graph is built, so LangGraph
|
|
coerces each run's `context=` payload into this dataclass — in-process,
|
|
`runtime.context` is a `CLIContextSchema` instance.
|
|
|
|
It exists alongside `CLIContext` (below) because the payload is shaped
|
|
differently on each side of the API boundary: in-process it is coerced to
|
|
this dataclass, but over the LangGraph API server (RemoteGraph) it is
|
|
serialized to JSON and arrives as a plain dict. Consumers
|
|
(`configurable_model._get_context`, `_should_interrupt_tool_call`)
|
|
therefore accept both shapes. `CLIContext` is the client-facing builder for
|
|
constructing that payload.
|
|
|
|
Fields mirror `CLIContext`; see its per-field docstrings for semantics.
|
|
"""
|
|
|
|
model: str | None = None
|
|
|
|
model_params: dict[str, Any] = field(default_factory=dict)
|
|
|
|
profile_overrides: dict[str, Any] = field(default_factory=dict)
|
|
|
|
model_context_limit: int | None = None
|
|
|
|
auto_approve: bool = False
|
|
|
|
approval_mode_key: str | None = None
|
|
|
|
thread_id: str | None = None
|
|
|
|
blocked_goal_retry_context: str | None = None
|
|
|
|
offload_tool_call_id: str | None = None
|
|
|
|
|
|
class CLIContext(TypedDict, total=False):
|
|
"""Client-facing builder for the per-run graph context payload.
|
|
|
|
Callers populate this and pass it via `context=` to `astream`/`ainvoke`.
|
|
`ConfigurableModelMiddleware` and the `interrupt_on` `when` predicate read
|
|
it from `request.runtime.context`. In-process LangGraph coerces it into
|
|
`CLIContextSchema` (the registered `context_schema`); over the API it stays
|
|
a plain dict — which is why consumers handle both shapes.
|
|
"""
|
|
|
|
model: str | None
|
|
"""Model spec to swap at runtime (e.g. `'provider:model'`)."""
|
|
|
|
model_params: dict[str, Any]
|
|
"""Invocation params (e.g. `temperature`, `max_tokens`) to merge
|
|
into `model_settings`."""
|
|
|
|
profile_overrides: dict[str, Any]
|
|
"""Model profile metadata supplied by `--profile-override`."""
|
|
|
|
model_context_limit: int | None
|
|
"""Effective context-window limit for profile-aware middleware."""
|
|
|
|
auto_approve: bool
|
|
"""Whether gated tool calls should skip the human-approval interrupt.
|
|
|
|
Sourced from the client session (not graph state) so the model cannot
|
|
self-approve by writing state. The `interrupt_on` `when` predicate reads
|
|
this to suppress interrupts at the source when "approve always" is on,
|
|
avoiding the interrupt-then-auto-resolve round-trip.
|
|
"""
|
|
|
|
approval_mode_key: str | None
|
|
"""Store key for the live approval-mode control record.
|
|
|
|
The TUI updates this record when the user toggles approval mode mid-run.
|
|
The server-side interrupt predicate reads it from the LangGraph Store on
|
|
each gated tool call so auto-to-manual changes can take effect before the
|
|
current stream returns.
|
|
"""
|
|
|
|
thread_id: str | None
|
|
"""LangGraph thread ID for the active conversation.
|
|
|
|
Mirrors `config.configurable.thread_id` into runtime context for model-call
|
|
middleware that needs per-request session identity, including Fireworks
|
|
session-affinity headers.
|
|
"""
|
|
|
|
blocked_goal_retry_context: str | None
|
|
"""One-turn model context for retrying a previously blocked goal.
|
|
|
|
This is intentionally carried in runtime context instead of the user
|
|
message so it is not parsed as a file mention or checkpointed as human
|
|
input.
|
|
"""
|
|
|
|
offload_tool_call_id: str | None
|
|
"""The sole tool-call ID authorized during a server-driven `/offload` run.
|
|
|
|
This is set by the client, not graph state, so model-generated calls cannot
|
|
grant themselves permission to execute during the hidden compaction turn.
|
|
"""
|