ChatDev Workflow Versioning and Storage Management: A Complete Technical Guide

ChatDev manages workflow versioning through a semantic version field in YAML design documents and stores both definitions and execution outputs in a secure, validated file-system hierarchy separated into YAML directories and per-session warehouses.

ChatDev, the multi-agent collaborative development framework by OpenBMB, treats every workflow as a version-aware YAML design document with strict storage governance. Understanding ChatDev workflow versioning and storage management is essential for maintaining reproducible AI-driven software engineering pipelines and securing multi-tenant deployments against path-traversal attacks.

How ChatDev Implements Workflow Versioning

ChatDev embeds versioning metadata directly into workflow definitions through the DesignConfig class in entity/configs/graph.py. This approach ensures that every workflow carries its own compatibility identifier without requiring external metadata databases.

The version Field in Design Documents

Every workflow YAML must contain a top-level version key that follows semantic versioning conventions. When check.check.load_config parses the file, it instantiates a DesignConfig object that exposes this value:


# Simplified from check/check.py → load_config

design = load_config(yaml_path)          # returns a DesignConfig instance

print(design.version)                    # e.g. "1.2.3"

The version string enables downstream CI pipelines and audit systems to enforce migration rules or compatibility checks before executing potentially breaking graph changes.

Default Version Handling

If the YAML omits the version key, DesignConfig.from_dict automatically injects "0.0.0" as the default value. This fallback is defined in entity/configs/graph.py (lines 273–284) and guarantees that no workflow object exists in an undefined state, allowing version comparison logic to proceed safely even on legacy files.

Secure Workflow Storage Architecture

The storage layer isolates workflow manipulation logic inside server/services/workflow_storage.py, providing a testable interface for filename validation, persistence, and renaming operations.

Filename Validation and Sanitization

Before any write operation, validate_workflow_filename enforces a strict whitelist pattern (^[a-zA-Z0-9._-]+$) that rejects path-traversal sequences (.., leading /) and mandates .yaml or .yml extensions. This validation runs consistently across persist_workflow, rename_workflow, and copy_workflow to prevent directory escape vulnerabilities in multi-tenant environments.

Persisting, Renaming, and Copying Workflows

The persist_workflow function (lines 37–66) writes raw YAML content to YAML_DIR / safe_filename, wrapping I/O failures in WorkflowExecutionError with structured logging. When renaming workflows via rename_workflow (lines 111–165), ChatDev automatically rewrites the internal id: field inside the YAML to match the new file stem through _update_workflow_id, preventing identifier drift. Both rename and copy operations guard against name collisions by raising ResourceConflictError if the target filename already exists.

Runtime Output and Warehouse Management

After execution, ChatDev archives artefacts in a dedicated warehouse directory structure defined by WARE_HOUSE_DIR in server/settings.py. This separation of design documents from runtime outputs enables clean backup strategies and analytics aggregation.

ResultArchiver and Execution Artefacts

The ResultArchiver.export method in workflow/runtime/result_archiver.py (lines 21–33) persists three key files after each run:

  • token_usage_<graph>.json: Contains counters from the TokenTracker instance
  • execution_logs.json: Structured logs captured by the LogManager
  • Final result artefacts: Returned via WebSocket and simultaneously written to the same directory by the executor

Directory Structure and Session Isolation

The base output path is constructed by combining WARE_HOUSE_DIR with a unique session identifier (e.g., WareHouse/session_12345). The GraphConfig class in entity/graph_config.py (lines 14–18) carries this output_root through the execution lifecycle, ensuring that concurrent workflow runs cannot overwrite each other's data. This deterministic layout supports batch-mode analytics and forensic debugging across multiple ChatDev sessions.

Practical Implementation Examples

Defining a Versioned Workflow

Create a YAML file with an explicit version string that DesignConfig will parse:


# my_workflow.yaml

version: "1.3.0"
id: my_workflow
vars:
  API_KEY: "${API_KEY}"
graph:
  nodes:
    - name: fetch_data
      type: python
      config:
        command: |
          import requests
          data = requests.get("https://api.example.com").json()
  edges:
    - source: fetch_data
      target: process_data

Exporting a Template with CLI Version Pinning

Use the export tool in tools/export_design_template.py to generate a template with a specific version:

python -m chatdev.tools.export_design_template \
    --output template.yaml \
    --version "2.0.0"

This creates a YAML document with version: "2.0.0" at the top level (see lines 37–40 in the source).

Persisting Workflows via the Python API

Programmatically store a workflow with full validation:

from pathlib import Path
from server.services.workflow_storage import validate_workflow_filename, persist_workflow

yaml_content = Path("my_workflow.yaml").read_text()
safe_name, yaml_obj = validate_workflow_filename("my_workflow.yaml", yaml_content)
persist_workflow(
    safe_filename=safe_name,
    content=yaml_content,
    yaml_content=yaml_obj,
    action="create",
    directory=Path("yaml_instance")   # Corresponds to YAML_DIR from settings

)

Renaming a Workflow with Automatic ID Updates

Rename a file while keeping the internal identifier synchronized:

from server.services.workflow_storage import rename_workflow

rename_workflow(
    source_filename="my_workflow.yaml",
    target_filename="my_new_workflow.yaml",
    directory=Path("yaml_instance")
)

Behind the scenes, this updates the id: field to my_new_workflow (see lines 111–165 in workflow_storage.py).

Accessing Archived Execution Results

Retrieve token usage and logs from a completed session:

from pathlib import Path
import json

output_dir = Path("WareHouse") / "session_12345"

with (output_dir / "token_usage_my_workflow.json").open() as f:
    token_usage = json.load(f)

with (output_dir / "execution_logs.json").open() as f:
    logs = json.load(f)

print("Tokens used:", token_usage)
print("Log entries:", len(logs))

These files are written by ResultArchiver.export as implemented in workflow/runtime/result_archiver.py.

Summary

  • Versioning is embedded in every workflow YAML via the version field managed by DesignConfig in entity/configs/graph.py, defaulting to "0.0.0" when omitted.
  • Storage security relies on server/services/workflow_storage.py functions that validate filenames against whitelist patterns and prevent path-traversal attacks.
  • Lifecycle operations like rename_workflow automatically synchronize the internal YAML id: field with the filesystem name to prevent reference drift.
  • Execution isolation is enforced through per-session warehouse directories configured in server/settings.py and managed by ResultArchiver in workflow/runtime/result_archiver.py.
  • Auditability is supported by deterministic output paths that separate design documents (YAML_DIR) from runtime artefacts (WARE_HOUSE_DIR).

Frequently Asked Questions

What happens if I omit the version field in my ChatDev workflow YAML?

If the version key is missing, DesignConfig.from_dict in entity/configs/graph.py automatically assigns the default value "0.0.0". This ensures that all workflow objects carry a comparable version identifier, preventing null-reference errors in downstream compatibility checks.

How does ChatDev prevent directory traversal attacks when saving workflows?

The validate_workflow_filename function in server/services/workflow_storage.py enforces a strict regex whitelist (^[a-zA-Z0-9._-]+$) that rejects path separators, parent-directory references (..), and absolute paths. Only files ending in .yaml or .yml are accepted, ensuring all writes remain confined to the designated YAML_DIR.

Where does ChatDev store execution logs and token usage after a workflow completes?

According to workflow/runtime/result_archiver.py, the ResultArchiver.export method writes token_usage_<graph>.json and execution_logs.json into a session-specific subdirectory under WARE_HOUSE_DIR (defined in server/settings.py). The exact path follows the pattern <output_root>/<graph_name>/, where output_root is injected via GraphConfig.

Can I rename a workflow file without breaking internal references?

Yes. The rename_workflow function in server/services/workflow_storage.py (lines 111–165) handles this atomically: it validates the new filename, checks for collisions, moves the file, and calls _update_workflow_id to rewrite the YAML's internal id: field to match the new file stem, maintaining consistency between the filesystem and the workflow definition.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →