# How ai-berkshire Manages State Across Different Skill Interactions: A Technical Deep Dive

> Learn how ai-berkshire manages state across skill interactions by exporting and reloading browser sessions via JSON files. Maintain authentication and resume operations seamlessly.

- Repository: [Xbt Lin/ai-berkshire](https://github.com/xbtlin/ai-berkshire)
- Tags: deep-dive
- Published: 2026-07-07

---

**ai-berkshire manages state across different skill interactions by exporting Playwright browser storage state to JSON files, then reloading these sessions via command-line arguments to maintain authentication without re-login, while using separate progress files to resume long-running operations.**

Managing persistent state in a multi-skill AI system presents unique challenges when individual skills are designed to be stateless. The **ai-berkshire** repository solves this by implementing a file-based persistence layer that captures browser sessions and checkpoints progress without requiring database infrastructure. This approach allows skills like the Xueqiu scraper to maintain authentication across process restarts while keeping the core framework lightweight and modular.

## The Stateless Design Challenge

The ai-berkshire skill framework operates on a **stateless-by-design** architecture, meaning individual skill invocations do not retain memory between executions. However, practical workflows—particularly web scraping tasks—require authenticated sessions that persist across multiple interactions. Rather than modifying the core architecture to support stateful connections, the repository leverages **Playwright's storage state API** to externalize session data to the filesystem.

## Persistence Through Playwright Storage State

The primary mechanism for state management involves exporting and re-importing browser context data, including cookies, local storage, and session information.

### Creating and Saving Sessions

When a skill requires initial authentication, it invokes the `interactive_login()` function. Upon successful login, this function writes the browser's complete storage state to a specified file path, capturing all necessary authentication tokens.

In [`tools/xueqiu_scraper.py`](https://github.com/xbtlin/ai-berkshire/blob/main/tools/xueqiu_scraper.py) (line 149), the implementation follows this pattern:

```python
async def interactive_login(pw, state_path, user_id):
    browser = await pw.chromium.launch()
    context = await browser.new_context()
    page = await context.new_page()
    
    # ... perform login sequence ...

    
    # After successful login, persist session data

    await context.storage_state(path=state_path)
    print(f"登录态已保存 → {state_path}")

```

The `storage_state` parameter directs Playwright to serialize the current browser context—including HTTP cookies, `localStorage`, and `IndexedDB`—into a portable JSON format.

### Restoring Previous Sessions

Subsequent executions avoid re-authentication by invoking `load_with_state()`, which checks for the existence of the state file and initializes the browser context with the preserved session data.

From [`tools/xueqiu_scraper.py`](https://github.com/xbtlin/ai-berkshire/blob/main/tools/xueqiu_scraper.py):

```python
async def load_with_state(pw, state_path, user_id):
    if not os.path.exists(state_path):
        return None
    browser = await pw.chromium.launch()
    # Restore session from previous run

    context = await browser.new_context(storage_state=state_path)
    page = await context.new_page()
    return browser, context, page

```

This pattern enables **rapid re-authentication** without user credential re-entry, as the inherited cookies maintain the server's session validation.

## Resumable Operations and Progress Tracking

For long-running scripts that may encounter interruptions, ai-berkshire implements a secondary checkpointing mechanism. The system writes progress files to track completed work, enabling jobs to resume from interruption points rather than restarting from scratch.

The progress file naming convention follows the pattern `{state_path}.progress.{user_id}`, as implemented around line 401 in [`tools/xueqiu_scraper.py`](https://github.com/xbtlin/ai-berkshire/blob/main/tools/xueqiu_scraper.py):

```python
progress_path = args.state_path + f'.progress.{args.user_id}'
if os.path.exists(progress_path):
    # Read checkpoint and continue from there

    resume_point = json.load(open(progress_path))
    # ... resume processing from resume_point ...

```

This dual-file approach—separating browser state from operational progress—allows skills to maintain both authentication continuity and data processing integrity across restarts.

## CLI Architecture and User Isolation

State persistence integrates directly into the command-line interface, ensuring consistent behavior across all skills. The entry point parses `--state_path` and `--user_id` arguments, making session management explicit and configurable for every invocation.

Example CLI usage:

```bash
python3 tools/xueqiu_scraper.py \
    --pw mypassword \
    --state_path /tmp/xueqiu_state.json \
    --user_id alice

```

**User isolation** occurs naturally through the file naming convention. By embedding the `user_id` into the progress filename (`{state_path}.progress.{user_id}`), multiple concurrent users can maintain independent session data and checkpoints without conflict. This design supports multi-tenant deployments where different users might simultaneously execute the same skill with distinct authentication states.

## Summary

- **ai-berkshire** uses **file-based state persistence** rather than in-memory or database storage to maintain compatibility with stateless skill architectures.
- The `interactive_login()` function in [`tools/xueqiu_scraper.py`](https://github.com/xbtlin/ai-berkshire/blob/main/tools/xueqiu_scraper.py) exports Playwright's `storage_state` to JSON files, preserving cookies and session data for authenticated services.
- The `load_with_state()` function re-imports these files using the `storage_state` parameter, enabling instant session restoration without re-authentication.
- **Progress tracking** uses `{state_path}.progress.{user_id}` files to checkpoint long-running operations, supporting fault-tolerant execution.
- **Command-line arguments** (`--state_path` and `--user_id`) wire state management into the skill runtime, with user-specific filenames ensuring isolation in multi-user environments.

## Frequently Asked Questions

### How does ai-berkshire handle authentication without storing passwords in memory?

The system stores only the browser's session cookies and storage state via Playwright's `storage_state` API, not the actual credentials. Once `interactive_login()` completes the initial authentication and exports the state file, subsequent runs load the session context directly from the JSON file, eliminating the need to retain passwords in environment variables or memory.

### Can multiple skills share the same session state file?

Yes, multiple skills can share the same `--state_path` argument to maintain a unified authentication context. However, the repository recommends coordinating access carefully, as Playwright storage state files are not designed for concurrent write access. Skills that only read the state file can operate simultaneously, while skills requiring session updates should execute sequentially or use separate state files.

### What happens if the state file becomes stale or expires?

If the `load_with_state()` function detects an expired or invalid session (typically manifesting as authentication failures on subsequent requests), the calling skill can fall back to invoking `interactive_login()` again. The scraper logic typically checks for specific error patterns or login redirects, then triggers a fresh authentication flow to overwrite the stale state file with new valid session data.

### Where does ai-berkshire store intermediate progress for long-running tasks?

The system stores progress checkpoints in separate JSON files using the naming pattern `{state_path}.progress.{user_id}`, as seen in the Xueqiu scraper implementation at line 401. These files contain serialized JSON objects tracking completion status, allowing the skill to resume from the exact interruption point by reading this file on startup if it exists.