TuBrief
Subscribed Channels
Videos
Community

How to Build a Local Backup to Save Agent Sessions Even When the OpenAI Assistants API Goes Down

TuBrief Editorial
August 7, 2026
0
Computing/Software

Written with AI assistance from the source video. The video is the authority.

English한국어Español中文العربيةहिन्दीDeutschFrançaisPortuguêsРусскийBahasa Indonesia日本語

Related Video

You don't own your AI agent sessions21:24

You don't own your AI agent sessions

Maximilian Schwarzmüller

More from the community

사내 시스템에 llm api 붙일 때 마주하는 현실적인 한계와 대응법

September 13, 2026

레거시 백엔드에 GPT-6 Astra 붙일 때 예산 승인과 보안 통과를 먼저 끝내는 법이 있습니다

September 13, 2026

에이전트끼리 대화하다 6천만 원 청구서가 나오는 이유

September 13, 2026

사내 RAG 벡터 검색에 Okta 권한 필터를 직접 거는 방법

September 13, 2026

브라우저 에이전트에게 내 구글 계정을 통째로 넘기면 안 되는 이유

September 12, 2026

Apple Won the AI Race

September 12, 2026

Comments (0)

Log in to leave a comment

No posts yet

© 2026 . All rights reserved.

TuBrief
Subscribed Channels
Videos
Community
Log in

How to Build a Local Backup to Save Agent Sessions Even When the OpenAI Assistants API Goes Down

Running a service with an AI agent alone can become tricky if the vendor API suddenly shuts down out of nowhere. If OpenAI completely shuts down the Assistants API v1 beta endpoint on August 26, 2026, the conversation threads and execution histories stored on their servers will instantly vanish. A structure that leaves all session states entirely to the vendor's server is no different from working with a ticking time bomb.

To avoid being dragged around by platforms, you need to bring conversation states into your own computer's file system. It is much safer to use LLMs as interchangeable computing tools while directly holding and controlling conversation contexts and prompt assets locally.

The Price Paid When Trapped in Cloud Agent Sessions

When you leave sessions on servers of providers like OpenAI or Anthropic, there is no way to know how conversation states are compressed and encrypted internally. When problems occur, auditing the internals becomes completely impossible. Because the entire context is reprocessed every time conversation turns accumulate, token costs increase quadratically. Code Interpreter costs of $0.03 per session or File Search storage costs of $0.10 per GB per month quietly drain your bank account.

Evaluation Criteria Cloud-Managed Sessions (OpenAI Assistants) Local File System Standalone Harness
Data Ownership Isolated on vendor servers (cannot export) Stored as JSON files in a local directory
Service Continuity Thread loss during API shutdown on August 26, 2026 Immediate switch to another model even if vendor servers crash
Context Cost Token waste due to full thread reprocessing per turn Token reduction by selectively injecting DiffMem changes
Debugging Transparency Unverifiable due to server-side opaque compression Direct verification of inference processes via local middleware logs

As Microsoft CEO Satya Nadella mentioned, the structure of leaving session management to model provider infrastructure is risky. This is because exclusively owned conversation contexts, not the models themselves, are the real assets. The "behavioral dependency" pointed out by 76% of developers in a Docker survey also ultimately arises from losing this session control.

Taking Back Session Control with a Local File System

Combining the LangGraph framework with a Custom Checkpointer allows you to securely fix conversation states into local JSON files. When writing data to files, use the atomic write method utilizing os.replace. Even if the power goes out or the process is forcibly killed during an operation, the data will not get corrupted.

`python
import json
import os
from datetime import datetime
from typing import Any, Dict, List
from dataclasses import dataclass, asdict

@dataclass
class LocalSessionState:
session_id: str
model_provider: str
model_name: str
system_prompt: str
messages: List[Dict[str, Any]]
metadata: Dict[str, Any]
updated_at: str

class LocalFileCheckpointer:
def init(self, base_dir: str = "./agent_workspace/sessions"):
self.base_dir = base_dir
os.makedirs(self.base_dir, exist_ok=True)

def _get_file_path(self, session_id: str) -> str:
    return os.path.join(self.base_dir, f"{session_id}.json")

def save_state(self, state: LocalSessionState) -> str:
    file_path = self._get_file_path(state.session_id)
    temp_path = f"{file_path}.tmp"
    state.updated_at = datetime.utcnow().isoformat()
    data = asdict(state)
    
    with open(temp_path, "w", encoding="utf-8") as f:
        json.dump(data, f, ensure_ascii=False, indent=2)
        
    os.replace(temp_path, file_path)
    return file_path

`

You can set up your session backup environment like this:

  1. Create agent_workspace inside your project folder, and place prompts/, sessions/, and logs/ directories underneath it respectively. Organize operation rules in AGENTS.md.
  2. Import LocalFileCheckpointer from the Python code above and connect it so that a snapshot is overwritten to a JSON file every time a conversation turn is updated.
  3. Attach the GitSessionVersioner below to your Git post-hook pipeline to automatically commit changes to Git whenever session files change.

`python
import subprocess

class GitSessionVersioner:
def init(self, repo_dir: str = "./agent_workspace"):
self.repo_dir = repo_dir
self._ensure_git_repo()

def _ensure_git_repo(self):
    if not os.path.exists(os.path.join(self.repo_dir, ".git")):
        subprocess.run(["git", "init"], cwd=self.repo_dir, check=True)

def commit_session(self, session_id: str, commit_message: str):
    file_name = f"sessions/{session_id}.json"
    subprocess.run(["git", "add", file_name], cwd=self.repo_dir, check=True)
    status = subprocess.run(["git", "status", "--porcelain", file_name], cwd=self.repo_dir, capture_output=True, text=True)
    if status.stdout.strip():
        subprocess.run(["git", "commit", "-m", f"session({session_id}): {commit_message}"], cwd=self.repo_dir, check=True)

`

Once this structure is established, even if conversation threads grow long, there is no need to forcefully shove the entire history into the context window. Since only DiffMem changes are selectively queried, unnecessary token expenses are prevented, and session restoration working time is reduced by over 2 hours.

Collecting Hidden Inference Logs via Local Middleware

Cloud APIs often completely conceal what agents are thinking and which tools they are calling. To eliminate debugging frustration, place LiteLLM Proxy or a middleware interceptor in the middle and directly log incoming and outgoing data to files. Spinning up open-source tracing tools like Langfuse or Weights & Biases Weave in local Docker lets you cleanly view differences such as OpenAI's type: function or Anthropic's input_schema all in one place.

`python
import json
import logging
from typing import Dict, Any, Optional

class AgentLoggingMiddleware:
def init(self, log_file_path: str):
self.logger = logging.getLogger("AgentLogger")
self.logger.setLevel(logging.DEBUG)
handler = logging.FileHandler(log_file_path, encoding="utf-8")
handler.setFormatter(logging.Formatter('[%(asctime)s] [%(levelname)s] %(message)s'))
self.logger.addHandler(handler)

def on_pre_tool_execution(self, tool_name: str, tool_args: Dict[str, Any], tool_call_id: str):
    log_entry = {"event": "PreToolUse", "tool_call_id": tool_call_id, "tool_name": tool_name, "arguments": tool_args}
    self.logger.info(f"TOOL_CALL_INIT: {json.dumps(log_entry, ensure_ascii=False)}")

def on_post_tool_execution(self, tool_call_id: str, result: Any, error: Optional[str] = None):
    log_entry = {"event": "PostToolUse", "tool_call_id": tool_call_id, "result": result, "error": error}
    if error:
        self.logger.error(f"TOOL_CALL_FAILED: {json.dumps(log_entry, ensure_ascii=False)}")
    else:
        self.logger.info(f"TOOL_CALL_SUCCESS: {json.dumps(log_entry, ensure_ascii=False)}")

`

Execution log collection is completed in three steps:

  1. Insert AgentLoggingMiddleware into the PreToolUse and PostToolUse points of the agent execution loop.
  2. Configure argument values passed during tool calls and raw text return values to be immediately recorded in file logs.
  3. Run Langfuse in a local Docker environment to track infinite retries or incorrect argument parsing during API communication on a single screen.

Even just properly accumulating logs allows you to find the root causes of errors exploding in tool arguments all at once. API token costs wasted running in pointless loops noticeably decrease.

How to Convert Schemas and Move from OpenAI to Claude

OpenAI APIs send and receive tool arguments as serialized JSON strings and have a separate tool role. On the other hand, the Anthropic Messages API uses parsed dictionary objects and a tool_result block inside user messages. Because the specifications differ, throwing backed-up JSON data as-is to Anthropic results in an HTTP 400 error. An adapter that aligns specifications in the middle is required.

`python
import json
from typing import List, Dict, Any, Tuple

class CrossModelSessionAdapter:
@staticmethod
def openai_to_anthropic_format(system_prompt: str, openai_messages: List[Dict[str, Any]]) -> Tuple[str, List[Dict[str, Any]]]:
anthropic_messages = []
i = 0
while i < len(openai_messages):
msg = openai_messages[i]
role = msg.get("role")
if role == "system":
system_prompt = msg.get("content", system_prompt)
i += 1
elif role == "user":
anthropic_messages.append({"role": "user", "content": msg.get("content")})
i += 1
elif role == "assistant":
content_blocks = []
if msg.get("content"):
content_blocks.append({"type": "text", "text": msg.get("content")})
if "tool_calls" in msg and msg["tool_calls"]:
for tc in msg["tool_calls"]:
args = tc["function"]["arguments"]
parsed_args = json.loads(args) if isinstance(args, str) else args
content_blocks.append({"type": "tool_use", "id": tc["id"], "name": tc["function"]["name"], "input": parsed_args})
anthropic_messages.append({"role": "assistant", "content": content_blocks})
i += 1
elif role == "tool":
tool_results = []
while i < len(openai_messages) and openai_messages[i].get("role") == "tool":
t_msg = openai_messages[i]
tool_results.append({"type": "tool_result", "tool_use_id": t_msg.get("tool_call_id"), "content": t_msg.get("content")})
i += 1
anthropic_messages.append({"role": "user", "content": tool_results})
return system_prompt, anthropic_messages

`

Migration work is also simple:

  1. Read conversation history and tool execution data from the local sessions/{session_id}.json file.
  2. Run CrossModelSessionAdapter to change the OpenAI format into the Anthropic specification.
  3. Put a context block specifying that this is continued work from the previous session at the top of the new model system prompt and send the request.

`text
[System Context Injection]
This conversation is continued work migrated from a previous session (ID: sess_99812).
Tool execution results and conversation context with the previous model are included in the message history.
Based on the presented previous tool call results (tool_result), resume work from the point where it was interrupted.

`

It doesn't matter if a specific vendor server breaks down or suddenly changes service policies. You can just switch to another LLM with a few lines of conversion code while maintaining conversation flow 100%. Business continuity for solo developers is finally secured when you physically hold session data in your own directory.