Author: kongastral

  • Building REST APIs with FastAPI: A Modern Python Web Framework Guide

    This post examines FastAPI in 2026 and demonstrates how to construct a production-ready REST API from scratch. In December 2018, a Colombian developer named Sebastián Ramírez pushed the first commit of a Python web framework to GitHub. Six years later, that project — FastAPI — has surpassed 80,000 stars, overtaken Flask in monthly downloads, and become the framework of choice at Netflix, Uber, Microsoft, and hundreds of startups building production APIs. The questions that arise are clear: what makes FastAPI so compelling that companies are rewriting entire API layers around it, and how can its capabilities be applied to build robust, production-ready REST APIs?

    For anyone familiar with the Python web ecosystem, the landscape has been dominated by two heavyweights for more than a decade: Flask, the minimalist micro-framework valued for its simplicity, and Django with its REST Framework, the batteries-included monolith favoured by enterprises. Both are excellent tools. They were designed, however, in a world before type hints became standard, before async was a first-class citizen in Python, and before API-first architectures became the default approach to building software.

    FastAPI was created in a different environment. It leverages modern Python features that make Python one of the most productive languages available today — type annotations, async/await, and Pydantic data validation — to deliver something that approaches a transformation in developer experience: ordinary annotated Python functions are written, and the framework automatically generates interactive API documentation, validates every request and response, and runs with performance that rivals Node.js and Go. This is not marketing rhetoric. Independent benchmarks consistently show FastAPI handling 2–5x more requests per second than Flask.

    This guide builds a complete REST API from zero to deployment. By the end, the reader will possess a fully functional task-management API with CRUD operations, database persistence, authentication, tests, and a production deployment strategy. Every code example is complete and runnable, permitting the reader to follow along step by step and conclude with a working API.

    The discussion follows.

    FastAPI Request-Response Lifecycle Client Browser / App HTTP FastAPI Routing + Validation Parsed Path Operation Your Python Function + Dependencies Result Response JSON + Status Code Response travels back to client

    Summary

    What this post covers: A zero-to-deployment FastAPI tutorial that builds a complete task-manager REST API with CRUD endpoints, Pydantic validation, SQLAlchemy persistence, JWT authentication, tests, and a production deployment strategy.

    Key insights:

    • FastAPI’s appeal is structural, not cosmetic—type hints + Pydantic + ASGI/Starlette give you automatic OpenAPI docs, request/response validation, and async I/O from the same function signature you would have written anyway.
    • Independent benchmarks show FastAPI handling 2–5x more requests per second than Flask, putting it in the same performance class as Node.js and Go for typical I/O-bound workloads.
    • Use Pydantic models as the single source of truth for request bodies, response shapes, and OpenAPI schema—if you find yourself duplicating field definitions between models and SQLAlchemy tables, you are doing it wrong.
    • Authentication is best implemented with FastAPI’s Depends() system: a single get_current_user dependency injected into protected routes keeps JWT decoding, expiry checks, and DB lookups out of your endpoint code.
    • For production, the right stack is Uvicorn (or Gunicorn with Uvicorn workers) behind Nginx, with structured logging, CORS configured explicitly per origin, and tests written against TestClient so they exercise the real ASGI app, not a mock.

    Main topics: Why FastAPI, Setting Up Your Environment, Your First API—Hello World, Building a Complete CRUD API—Task Manager, Request Validation and Pydantic Models, Path Parameters Query Parameters and Request Body, Adding a Database with SQLAlchemy, Authentication and Security, Middleware CORS and Error Handling, Testing Your API, Deployment, Best Practices.

    Why FastAPI?

    Before any code is written, the characteristics that distinguish FastAPI and explain its rapid adoption in the Python community warrant examination.

    Automatic OpenAPI and Swagger Documentation

    Every FastAPI application automatically generates an OpenAPI schema and serves an interactive Swagger UI at /docs and a ReDoc interface at /redoc. No plugins must be installed, no YAML files written, and no separate documentation maintained. The code is the documentation, and the two are always in sync.

    Type Hints and Pydantic Validation

    FastAPI is built on top of Pydantic, the most widely used data-validation library in Python. Request and response models are defined as simple Python classes with type annotations, and FastAPI automatically validates incoming data, serialises outgoing data, and generates accurate schema documentation — all from the same model definition.

    Native Async Support

    FastAPI natively supports Python’s async/await syntax. This permits the API to handle thousands of concurrent connections efficiently without blocking, which is critical for I/O-bound workloads such as database queries, external API calls, and file operations. Regular synchronous functions are also supported; FastAPI handles both seamlessly.

    Performance Comparable to Node.js and Go

    Owing to its ASGI foundation (powered by Starlette) and the Uvicorn server, FastAPI delivers exceptional performance. In the TechEmpower Web Framework Benchmarks, Python ASGI frameworks consistently outperform traditional WSGI frameworks by significant margins.

    Framework Comparison

    Feature FastAPI Flask Django REST Express.js
    Auto Documentation Built-in Plugin required Plugin required Plugin required
    Data Validation Built-in (Pydantic) Manual / Marshmallow Built-in (Serializers) Manual / Joi
    Async Support Native Limited Django 4.1+ Native
    Performance (req/s) ~15,000+ ~3,000 ~2,500 ~18,000+
    Learning Curve Easy Very Easy Moderate Easy
    Type Safety Full (type hints) None Partial TypeScript optional
    Dependency Injection Built-in No No No

     

    Key Takeaway: FastAPI provides the simplicity of Flask, the features of Django REST Framework, and performance that approaches Node.js — all in one package. For any new Python API project in 2026, FastAPI is the appropriate default choice.

    FastAPI Architecture Layers Routes (Path Operations) @app.get(“/tasks”) @app.post(“/tasks”) @app.put(“/tasks/{id}”) @app.delete(“/tasks/{id}”) Dependencies (Dependency Injection) Auth verification · DB session · Rate limiting · Request parsing Services (Business Logic) Validation rules · Data transformation · Error handling · Domain logic Database (SQLAlchemy / ORM)

    Setting Up Your Environment

    A clean development environment is the appropriate starting point. The discussion uses Python 3.11+ (though 3.9+ is also acceptable) and creates an isolated virtual environment for the project.

    Verify the Python Installation

    python3 --version
    # Python 3.11.x or higher recommended

    Create the Project Directory

    mkdir fastapi-task-manager
    cd fastapi-task-manager

    Set Up a Virtual Environment

    Two options are available. The classic venv approach is one:

    # Option 1: Classic venv
    python3 -m venv venv
    source venv/bin/activate  # On Windows: venv\Scripts\activate
    
    # Option 2: Using uv (much faster)
    pip install uv
    uv venv
    source .venv/bin/activate
    Tip: Anyone unfamiliar with uv should consider trying it. It is a Rust-based Python package manager that installs dependencies 10–100x faster than pip and is rapidly becoming the standard tool for Python project management.

    Install FastAPI and Uvicorn

    # Install FastAPI with all optional dependencies
    pip install "fastapi[standard]"
    
    # This installs:
    # - fastapi (the framework)
    # - uvicorn (the ASGI server)
    # - pydantic (data validation)
    # - starlette (the underlying ASGI toolkit)
    # - httpx (for testing)
    # - python-multipart (for form data)
    # - jinja2 (for templates, if needed)

    Project Structure

    A clean project structure that will scale as the API grows is appropriate from the outset:

    fastapi-task-manager/
    ├── app/
    │   ├── __init__.py
    │   ├── main.py            # FastAPI app entry point
    │   ├── models.py           # Pydantic models (schemas)
    │   ├── database.py         # Database configuration
    │   ├── crud.py             # Database operations
    │   ├── auth.py             # Authentication logic
    │   └── routers/
    │       ├── __init__.py
    │       └── tasks.py        # Task endpoints
    ├── tests/
    │   ├── __init__.py
    │   └── test_tasks.py       # API tests
    ├── requirements.txt
    ├── Dockerfile
    └── .env

    Create the initial directory structure:

    mkdir -p app/routers tests
    touch app/__init__.py app/routers/__init__.py tests/__init__.py

    A First API: Hello World

    The most direct illustration begins with the simplest possible FastAPI application. The framework’s behaviour can then be observed.

    Create app/main.py:

    from fastapi import FastAPI
    
    app = FastAPI(
        title="Task Manager API",
        description="A complete REST API for managing tasks",
        version="1.0.0",
    )
    
    
    @app.get("/")
    def read_root():
        return {"message": "Welcome to the Task Manager API"}
    
    
    @app.get("/health")
    def health_check():
        return {"status": "healthy"}

    That is the entire requirement. Seven lines of actual code produce a working API with two endpoints. The application is run as follows:

    uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

    The --reload flag enables hot reloading, so the server restarts automatically when code is changed. Output of the following form should appear:

    INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
    INFO:     Started reloader process [12345]
    INFO:     Started server process [12346]
    INFO:     Waiting for application startup.
    INFO:     Application startup complete.

    Exploring the Swagger UI

    Opening a browser at http://localhost:8000/docs reveals an attractive interactive API documentation page, generated entirely from the code. Any endpoint may be clicked, “Try it out” selected, and requests executed directly from the browser.

    The alternative documentation layout is available at http://localhost:8000/redoc, and the raw OpenAPI schema — importable into Postman, Insomnia, or any API client — is available at http://localhost:8000/openapi.json.

    Key Takeaway: No documentation code has been written, yet a fully interactive API explorer is available. This is one of FastAPI’s distinguishing features: code and documentation are always in sync because they are the same artefact.

    Building a Complete CRUD API: Task Manager

    The following section constructs a substantive example: a full task-management API with all CRUD operations, proper validation, error handling, and correct HTTP status codes. The discussion begins with in-memory storage to focus on API design, and a database is added later.

    REST API HTTP Methods Method Endpoint Action Status Code GET /tasks /tasks/{id} Read (list or single) 200 OK POST /tasks Create new resource 201 Created PUT /tasks/{id} Replace full resource 200 OK DELETE /tasks/{id} Remove resource 204 No Content

    Define Pydantic Models

    The first step is to define the data models. Create app/models.py:

    from pydantic import BaseModel, Field
    from typing import Optional
    from datetime import datetime
    from enum import Enum
    
    
    class TaskStatus(str, Enum):
        pending = "pending"
        in_progress = "in_progress"
        completed = "completed"
        cancelled = "cancelled"
    
    
    class TaskCreate(BaseModel):
        title: str = Field(
            ...,
            min_length=1,
            max_length=200,
            description="The title of the task",
            examples=["Buy groceries"],
        )
        description: Optional[str] = Field(
            None,
            max_length=2000,
            description="Detailed description of the task",
        )
        status: TaskStatus = Field(
            default=TaskStatus.pending,
            description="Current status of the task",
        )
        priority: int = Field(
            default=1,
            ge=1,
            le=5,
            description="Priority level from 1 (lowest) to 5 (highest)",
        )
    
    
    class TaskUpdate(BaseModel):
        title: Optional[str] = Field(
            None,
            min_length=1,
            max_length=200,
        )
        description: Optional[str] = Field(None, max_length=2000)
        status: Optional[TaskStatus] = None
        priority: Optional[int] = Field(None, ge=1, le=5)
    
    
    class TaskResponse(BaseModel):
        id: int
        title: str
        description: Optional[str] = None
        status: TaskStatus
        priority: int
        created_at: datetime
        updated_at: datetime

    The separation of concerns is important: TaskCreate represents what clients send when creating a task, TaskUpdate allows partial updates (all fields optional), and TaskResponse represents what the API returns. This is a critical design pattern; the internal data model should never be exposed directly.

    Build the CRUD Endpoints

    The actual API can now be built. Update app/main.py:

    from fastapi import FastAPI, HTTPException, Query
    from typing import Optional
    from datetime import datetime
    
    from app.models import TaskCreate, TaskUpdate, TaskResponse, TaskStatus
    
    app = FastAPI(
        title="Task Manager API",
        description="A complete REST API for managing tasks",
        version="1.0.0",
    )
    
    # In-memory storage
    tasks_db: dict[int, dict] = {}
    task_id_counter = 0
    
    
    def get_next_id() -> int:
        global task_id_counter
        task_id_counter += 1
        return task_id_counter
    
    
    @app.get("/")
    def read_root():
        return {"message": "Welcome to the Task Manager API"}
    
    
    @app.get("/tasks", response_model=list[TaskResponse])
    def list_tasks(
        status: Optional[TaskStatus] = Query(
            None, description="Filter tasks by status"
        ),
        priority: Optional[int] = Query(
            None, ge=1, le=5, description="Filter tasks by priority"
        ),
        skip: int = Query(0, ge=0, description="Number of tasks to skip"),
        limit: int = Query(
            20, ge=1, le=100, description="Maximum number of tasks to return"
        ),
    ):
        """Retrieve all tasks with optional filtering and pagination."""
        results = list(tasks_db.values())
    
        # Apply filters
        if status is not None:
            results = [t for t in results if t["status"] == status]
        if priority is not None:
            results = [t for t in results if t["priority"] == priority]
    
        # Apply pagination
        return results[skip : skip + limit]
    
    
    @app.get("/tasks/{task_id}", response_model=TaskResponse)
    def get_task(task_id: int):
        """Retrieve a single task by its ID."""
        if task_id not in tasks_db:
            raise HTTPException(
                status_code=404,
                detail=f"Task with ID {task_id} not found",
            )
        return tasks_db[task_id]
    
    
    @app.post("/tasks", response_model=TaskResponse, status_code=201)
    def create_task(task: TaskCreate):
        """Create a new task."""
        now = datetime.utcnow()
        task_id = get_next_id()
    
        task_data = {
            "id": task_id,
            "title": task.title,
            "description": task.description,
            "status": task.status,
            "priority": task.priority,
            "created_at": now,
            "updated_at": now,
        }
        tasks_db[task_id] = task_data
        return task_data
    
    
    @app.put("/tasks/{task_id}", response_model=TaskResponse)
    def update_task(task_id: int, task_update: TaskUpdate):
        """Update an existing task. Only provided fields will be updated."""
        if task_id not in tasks_db:
            raise HTTPException(
                status_code=404,
                detail=f"Task with ID {task_id} not found",
            )
    
        existing_task = tasks_db[task_id]
        update_data = task_update.model_dump(exclude_unset=True)
    
        for field, value in update_data.items():
            existing_task[field] = value
    
        existing_task["updated_at"] = datetime.utcnow()
        return existing_task
    
    
    @app.delete("/tasks/{task_id}", status_code=204)
    def delete_task(task_id: int):
        """Delete a task by its ID."""
        if task_id not in tasks_db:
            raise HTTPException(
                status_code=404,
                detail=f"Task with ID {task_id} not found",
            )
        del tasks_db[task_id]

    The key design decisions in this code merit explanation:

    Status code 201 for creation: The POST /tasks endpoint returns 201 (Created) instead of the default 200, which is the correct HTTP semantic for resource creation.

    Status code 204 for deletion: The DELETE endpoint returns 204 (No Content) with no response body, which is the standard for successful deletions.

    HTTPException for errors: When a task is not found, an HTTPException is raised with a 404 status code and a human-readable detail message. FastAPI converts this into a proper JSON error response automatically.

    Partial updates with exclude_unset: The model_dump(exclude_unset=True) call on the update model ensures that only fields explicitly sent by the client are updated. This is the correct behaviour for a PUT/PATCH endpoint.

    Testing the CRUD API

    The server is started with uvicorn app.main:app --reload, and the following requests may then be issued using curl:

    # Create a task
    curl -X POST http://localhost:8000/tasks \
      -H "Content-Type: application/json" \
      -d '{"title": "Learn FastAPI", "description": "Complete the tutorial", "priority": 5}'
    
    # List all tasks
    curl http://localhost:8000/tasks
    
    # Get a specific task
    curl http://localhost:8000/tasks/1
    
    # Update a task
    curl -X PUT http://localhost:8000/tasks/1 \
      -H "Content-Type: application/json" \
      -d '{"status": "in_progress"}'
    
    # Filter tasks by status
    curl "http://localhost:8000/tasks?status=in_progress"
    
    # Delete a task
    curl -X DELETE http://localhost:8000/tasks/1
    Tip: All of these endpoints can also be tested interactively through the Swagger UI at http://localhost:8000/docs. It is much faster for exploration than writing curl commands.

    Request Validation and Pydantic Models

    One of FastAPI’s most powerful features is its deep integration with Pydantic for data validation. The capabilities of Pydantic beyond the basics already discussed are examined below.

    Field Validation

    Pydantic’s Field function provides fine-grained control over validation:

    from pydantic import BaseModel, Field, field_validator
    import re
    
    
    class UserCreate(BaseModel):
        username: str = Field(
            ...,
            min_length=3,
            max_length=50,
            pattern=r"^[a-zA-Z0-9_]+$",
            description="Username (letters, numbers, underscores only)",
        )
        email: str = Field(
            ...,
            min_length=5,
            max_length=255,
            description="Valid email address",
        )
        age: int = Field(
            ...,
            gt=0,
            lt=150,
            description="Age in years",
        )
        score: float = Field(
            default=0.0,
            ge=0.0,
            le=100.0,
            description="Score between 0 and 100",
        )
    
        @field_validator("email")
        @classmethod
        def validate_email(cls, v: str) -> str:
            if "@" not in v or "." not in v.split("@")[-1]:
                raise ValueError("Invalid email address")
            return v.lower()

    The validation constraints available include:

    • min_length / max_length — for strings
    • pattern — regex validation for strings
    • gt / ge / lt / le — greater than, greater or equal, less than, less or equal, for numbers
    • multiple_of — ensures a number is a multiple of a given value

    Nested Models

    Pydantic models can be nested to represent complex data structures:

    from pydantic import BaseModel
    from typing import Optional
    
    
    class Address(BaseModel):
        street: str
        city: str
        state: str
        zip_code: str
        country: str = "US"
    
    
    class ContactInfo(BaseModel):
        email: str
        phone: Optional[str] = None
        address: Optional[Address] = None
    
    
    class Employee(BaseModel):
        name: str
        department: str
        contact: ContactInfo
        tags: list[str] = []
    
    
    # This would be valid JSON input:
    # {
    #     "name": "Alice",
    #     "department": "Engineering",
    #     "contact": {
    #         "email": "alice@example.com",
    #         "address": {
    #             "street": "123 Main St",
    #             "city": "San Francisco",
    #             "state": "CA",
    #             "zip_code": "94102"
    #         }
    #     },
    #     "tags": ["python", "fastapi"]
    # }

    Custom Validators

    For complex validation logic that goes beyond simple field constraints, Pydantic offers model validators that can validate relationships between fields:

    from pydantic import BaseModel, model_validator
    from datetime import date
    
    
    class DateRange(BaseModel):
        start_date: date
        end_date: date
    
        @model_validator(mode="after")
        def validate_date_range(self):
            if self.end_date < self.start_date:
                raise ValueError("end_date must be after start_date")
            return self
    
    
    class PasswordChange(BaseModel):
        current_password: str
        new_password: str = Field(min_length=8)
        confirm_password: str
    
        @model_validator(mode="after")
        def passwords_match(self):
            if self.new_password != self.confirm_password:
                raise ValueError("new_password and confirm_password must match")
            if self.new_password == self.current_password:
                raise ValueError("New password must differ from current password")
            return self

    When validation fails, FastAPI automatically returns a 422 (Unprocessable Entity) response with detailed error messages explaining exactly what went wrong and where. Clients receive clear, actionable error messages without any error-handling code having to be written.

    Path Parameters, Query Parameters, and Request Body

    FastAPI provides elegant means of extracting data from every part of an HTTP request. Each mechanism is examined below.

    Path Parameters

    Path parameters are extracted directly from the URL path and are always required:

    from fastapi import Path
    
    @app.get("/tasks/{task_id}/comments/{comment_id}")
    def get_comment(
        task_id: int = Path(..., gt=0, description="The task ID"),
        comment_id: int = Path(..., gt=0, description="The comment ID"),
    ):
        return {"task_id": task_id, "comment_id": comment_id}

    Query Parameters with Pagination

    Query parameters are well suited to filtering, sorting, and pagination:

    from fastapi import Query
    from typing import Optional
    from enum import Enum
    
    
    class SortField(str, Enum):
        created_at = "created_at"
        priority = "priority"
        title = "title"
    
    
    class SortOrder(str, Enum):
        asc = "asc"
        desc = "desc"
    
    
    @app.get("/tasks")
    def list_tasks(
        # Filtering
        status: Optional[TaskStatus] = Query(None),
        priority: Optional[int] = Query(None, ge=1, le=5),
        search: Optional[str] = Query(
            None, min_length=1, max_length=100,
            description="Search in title and description",
        ),
        # Sorting
        sort_by: SortField = Query(
            SortField.created_at, description="Field to sort by"
        ),
        order: SortOrder = Query(
            SortOrder.desc, description="Sort order"
        ),
        # Pagination
        skip: int = Query(0, ge=0, description="Records to skip"),
        limit: int = Query(20, ge=1, le=100, description="Max records"),
    ):
        """List tasks with filtering, sorting, and pagination."""
        results = list(tasks_db.values())
    
        if status:
            results = [t for t in results if t["status"] == status]
        if priority:
            results = [t for t in results if t["priority"] == priority]
        if search:
            results = [
                t for t in results
                if search.lower() in t["title"].lower()
                or (t["description"] and search.lower() in t["description"].lower())
            ]
    
        reverse = order == SortOrder.desc
        results.sort(key=lambda t: t[sort_by.value], reverse=reverse)
    
        return {
            "total": len(results),
            "skip": skip,
            "limit": limit,
            "tasks": results[skip : skip + limit],
        }

    Combining Path, Query, and Body in One Endpoint

    from fastapi import Path, Query, Body
    
    @app.put("/projects/{project_id}/tasks/{task_id}")
    def update_project_task(
        project_id: int = Path(..., gt=0),       # From URL path
        task_id: int = Path(..., gt=0),          # From URL path
        notify: bool = Query(False),              # From query string
        task_update: TaskUpdate = Body(...),      # From request body
    ):
        """
        URL: PUT /projects/5/tasks/42?notify=true
        Body: {"title": "Updated title", "priority": 3}
        """
        # project_id = 5 (from path)
        # task_id = 42 (from path)
        # notify = True (from query)
        # task_update = TaskUpdate(title="Updated title", priority=3) (from body)
        return {
            "project_id": project_id,
            "task_id": task_id,
            "notify": notify,
            "updates": task_update.model_dump(exclude_unset=True),
        }

    FastAPI automatically determines where each parameter originates based on its type: simple types are path or query parameters, while Pydantic models constitute the request body. The Path, Query, and Body functions allow validation and documentation to be attached to each.

    Adding a Database with SQLAlchemy

    In-memory storage is acceptable for prototyping, but any real application requires persistent data storage. The following section integrates SQLite with SQLAlchemy; the same pattern works with PostgreSQL, MySQL, or any other database.

    Install Database Dependencies

    pip install sqlalchemy

    Database Configuration

    Create app/database.py:

    from sqlalchemy import create_engine
    from sqlalchemy.orm import sessionmaker, DeclarativeBase
    
    SQLALCHEMY_DATABASE_URL = "sqlite:///./tasks.db"
    # For PostgreSQL:
    # SQLALCHEMY_DATABASE_URL = "postgresql://user:password@localhost/dbname"
    
    engine = create_engine(
        SQLALCHEMY_DATABASE_URL,
        connect_args={"check_same_thread": False},  # SQLite only
    )
    
    SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
    
    
    class Base(DeclarativeBase):
        pass
    
    
    def get_db():
        """Dependency that provides a database session per request."""
        db = SessionLocal()
        try:
            yield db
        finally:
            db.close()

    Define Database Models

    Create app/db_models.py:

    from sqlalchemy import Column, Integer, String, DateTime, Enum as SQLEnum
    from sqlalchemy.sql import func
    
    from app.database import Base
    from app.models import TaskStatus
    
    
    class TaskDB(Base):
        __tablename__ = "tasks"
    
        id = Column(Integer, primary_key=True, index=True, autoincrement=True)
        title = Column(String(200), nullable=False)
        description = Column(String(2000), nullable=True)
        status = Column(
            SQLEnum(TaskStatus), default=TaskStatus.pending, nullable=False
        )
        priority = Column(Integer, default=1, nullable=False)
        created_at = Column(
            DateTime(timezone=True), server_default=func.now()
        )
        updated_at = Column(
            DateTime(timezone=True),
            server_default=func.now(),
            onupdate=func.now(),
        )

    CRUD Operations Module

    Create app/crud.py to separate database logic from endpoint logic:

    from sqlalchemy.orm import Session
    from typing import Optional
    
    from app.db_models import TaskDB
    from app.models import TaskCreate, TaskUpdate, TaskStatus
    
    
    def get_tasks(
        db: Session,
        status: Optional[TaskStatus] = None,
        priority: Optional[int] = None,
        skip: int = 0,
        limit: int = 20,
    ) -> list[TaskDB]:
        query = db.query(TaskDB)
    
        if status is not None:
            query = query.filter(TaskDB.status == status)
        if priority is not None:
            query = query.filter(TaskDB.priority == priority)
    
        return query.offset(skip).limit(limit).all()
    
    
    def get_task(db: Session, task_id: int) -> Optional[TaskDB]:
        return db.query(TaskDB).filter(TaskDB.id == task_id).first()
    
    
    def create_task(db: Session, task: TaskCreate) -> TaskDB:
        db_task = TaskDB(**task.model_dump())
        db.add(db_task)
        db.commit()
        db.refresh(db_task)
        return db_task
    
    
    def update_task(
        db: Session, task_id: int, task_update: TaskUpdate
    ) -> Optional[TaskDB]:
        db_task = db.query(TaskDB).filter(TaskDB.id == task_id).first()
        if db_task is None:
            return None
    
        update_data = task_update.model_dump(exclude_unset=True)
        for field, value in update_data.items():
            setattr(db_task, field, value)
    
        db.commit()
        db.refresh(db_task)
        return db_task
    
    
    def delete_task(db: Session, task_id: int) -> bool:
        db_task = db.query(TaskDB).filter(TaskDB.id == task_id).first()
        if db_task is None:
            return False
        db.delete(db_task)
        db.commit()
        return True

    Refactored Endpoints with Database

    The endpoints in app/main.py are now updated to use the database:

    from fastapi import FastAPI, HTTPException, Query, Depends
    from sqlalchemy.orm import Session
    from typing import Optional
    
    from app.models import (
        TaskCreate, TaskUpdate, TaskResponse, TaskStatus,
    )
    from app.database import engine, get_db
    from app.db_models import Base
    from app import crud
    
    # Create database tables on startup
    Base.metadata.create_all(bind=engine)
    
    app = FastAPI(
        title="Task Manager API",
        description="A complete REST API for managing tasks",
        version="1.0.0",
    )
    
    
    @app.get("/")
    def read_root():
        return {"message": "Welcome to the Task Manager API"}
    
    
    @app.get("/tasks", response_model=list[TaskResponse])
    def list_tasks(
        status: Optional[TaskStatus] = Query(None),
        priority: Optional[int] = Query(None, ge=1, le=5),
        skip: int = Query(0, ge=0),
        limit: int = Query(20, ge=1, le=100),
        db: Session = Depends(get_db),
    ):
        """Retrieve all tasks with optional filtering and pagination."""
        return crud.get_tasks(db, status=status, priority=priority,
                              skip=skip, limit=limit)
    
    
    @app.get("/tasks/{task_id}", response_model=TaskResponse)
    def get_task(task_id: int, db: Session = Depends(get_db)):
        """Retrieve a single task by its ID."""
        task = crud.get_task(db, task_id)
        if task is None:
            raise HTTPException(status_code=404,
                                detail=f"Task {task_id} not found")
        return task
    
    
    @app.post("/tasks", response_model=TaskResponse, status_code=201)
    def create_task(task: TaskCreate, db: Session = Depends(get_db)):
        """Create a new task."""
        return crud.create_task(db, task)
    
    
    @app.put("/tasks/{task_id}", response_model=TaskResponse)
    def update_task(
        task_id: int,
        task_update: TaskUpdate,
        db: Session = Depends(get_db),
    ):
        """Update an existing task."""
        task = crud.update_task(db, task_id, task_update)
        if task is None:
            raise HTTPException(status_code=404,
                                detail=f"Task {task_id} not found")
        return task
    
    
    @app.delete("/tasks/{task_id}", status_code=204)
    def delete_task(task_id: int, db: Session = Depends(get_db)):
        """Delete a task by its ID."""
        if not crud.delete_task(db, task_id):
            raise HTTPException(status_code=404,
                                detail=f"Task {task_id} not found")

    The key change is the Depends(get_db) pattern. This is FastAPI’s dependency injection system: it automatically creates a database session for each request and closes it when the request is complete, even if an error occurs. The pattern is clean, testable, and avoids global state.

    Tip: For new projects, SQLModel may be preferable to separate SQLAlchemy and Pydantic models. Created by the same author as FastAPI, SQLModel permits a single class to serve as both Pydantic model and SQLAlchemy model, significantly reducing duplication.

    Authentication and Security

    No production API is complete without authentication. Two approaches are implemented below: a simple API key for server-to-server communication, and JWT tokens for user-facing authentication.

    Simple API Key Authentication

    Create app/auth.py:

    from fastapi import Depends, HTTPException, Security, status
    from fastapi.security import APIKeyHeader, OAuth2PasswordBearer, OAuth2PasswordRequestForm
    from jose import JWTError, jwt
    from passlib.context import CryptContext
    from datetime import datetime, timedelta
    from typing import Optional
    from pydantic import BaseModel
    
    # ── API Key Authentication ──────────────────────────
    
    API_KEY = "your-secret-api-key-here"  # In production, load from env
    api_key_header = APIKeyHeader(name="X-API-Key")
    
    
    def verify_api_key(api_key: str = Security(api_key_header)):
        if api_key != API_KEY:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="Invalid API key",
            )
        return api_key
    
    
    # ── JWT Authentication ──────────────────────────────
    
    SECRET_KEY = "your-jwt-secret-key"  # In production, load from env
    ALGORITHM = "HS256"
    ACCESS_TOKEN_EXPIRE_MINUTES = 30
    
    pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
    oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
    
    
    class Token(BaseModel):
        access_token: str
        token_type: str
    
    
    class TokenData(BaseModel):
        username: Optional[str] = None
    
    
    class User(BaseModel):
        username: str
        email: str
        disabled: bool = False
    
    
    class UserInDB(User):
        hashed_password: str
    
    
    # Simulated user database
    fake_users_db = {
        "admin": {
            "username": "admin",
            "email": "admin@example.com",
            "hashed_password": pwd_context.hash("secretpassword"),
            "disabled": False,
        }
    }
    
    
    def verify_password(plain_password: str, hashed_password: str) -> bool:
        return pwd_context.verify(plain_password, hashed_password)
    
    
    def create_access_token(
        data: dict, expires_delta: Optional[timedelta] = None
    ) -> str:
        to_encode = data.copy()
        expire = datetime.utcnow() + (
            expires_delta or timedelta(minutes=15)
        )
        to_encode.update({"exp": expire})
        return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    
    
    def get_current_user(token: str = Depends(oauth2_scheme)) -> User:
        credentials_exception = HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Could not validate credentials",
            headers={"WWW-Authenticate": "Bearer"},
        )
        try:
            payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
            username: str = payload.get("sub")
            if username is None:
                raise credentials_exception
        except JWTError:
            raise credentials_exception
    
        user_data = fake_users_db.get(username)
        if user_data is None:
            raise credentials_exception
    
        return User(**user_data)

    Protecting Endpoints

    Any endpoint can now be protected by adding the dependency:

    from app.auth import (
        verify_api_key, get_current_user, User, Token,
        create_access_token, verify_password, fake_users_db,
        ACCESS_TOKEN_EXPIRE_MINUTES,
    )
    from fastapi.security import OAuth2PasswordRequestForm
    
    
    # Token endpoint for JWT login
    @app.post("/token", response_model=Token)
    def login(form_data: OAuth2PasswordRequestForm = Depends()):
        user_data = fake_users_db.get(form_data.username)
        if not user_data or not verify_password(
            form_data.password, user_data["hashed_password"]
        ):
            raise HTTPException(
                status_code=401,
                detail="Incorrect username or password",
                headers={"WWW-Authenticate": "Bearer"},
            )
    
        access_token = create_access_token(
            data={"sub": form_data.username},
            expires_delta=timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES),
        )
        return {"access_token": access_token, "token_type": "bearer"}
    
    
    # Protected endpoint — requires JWT token
    @app.get("/users/me", response_model=User)
    def read_users_me(current_user: User = Depends(get_current_user)):
        return current_user
    
    
    # Protected endpoint — requires API key
    @app.delete("/admin/clear-tasks", dependencies=[Depends(verify_api_key)])
    def clear_all_tasks(db: Session = Depends(get_db)):
        db.query(TaskDB).delete()
        db.commit()
        return {"message": "All tasks deleted"}

    Install the required packages for JWT authentication:

    pip install python-jose[cryptography] passlib[bcrypt]
    Caution: Secret keys and passwords must never be hard-coded in source code. In a production application, SECRET_KEY, API_KEY, and database credentials should always be loaded from environment variables using python-dotenv or pydantic-settings. The hard-coded values here are for tutorial purposes only. For a broader treatment of containerising the API securely, see the related Docker containers explained guide.

    Middleware, CORS, and Error Handling

    As the API grows, cross-cutting concerns such as CORS support (so that frontends can call the API), request logging, and global error handling become necessary.

    Adding CORS for Frontend Access

    from fastapi.middleware.cors import CORSMiddleware
    
    app.add_middleware(
        CORSMiddleware,
        allow_origins=[
            "http://localhost:3000",      # React dev server
            "https://yourdomain.com",      # Production frontend
        ],
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
    )

    Custom Middleware for Logging and Timing

    import time
    import logging
    from fastapi import Request
    
    logger = logging.getLogger("api")
    
    
    @app.middleware("http")
    async def log_requests(request: Request, call_next):
        start_time = time.time()
    
        # Process the request
        response = await call_next(request)
    
        # Calculate duration
        duration = time.time() - start_time
    
        logger.info(
            f"{request.method} {request.url.path} "
            f"- Status: {response.status_code} "
            f"- Duration: {duration:.3f}s"
        )
    
        # Add timing header to response
        response.headers["X-Process-Time"] = f"{duration:.3f}"
        return response

    Global Exception Handlers

    from fastapi import Request
    from fastapi.responses import JSONResponse
    
    
    @app.exception_handler(ValueError)
    async def value_error_handler(request: Request, exc: ValueError):
        return JSONResponse(
            status_code=400,
            content={
                "error": "Bad Request",
                "detail": str(exc),
            },
        )
    
    
    @app.exception_handler(Exception)
    async def general_exception_handler(request: Request, exc: Exception):
        logger.error(f"Unhandled exception: {exc}", exc_info=True)
        return JSONResponse(
            status_code=500,
            content={
                "error": "Internal Server Error",
                "detail": "An unexpected error occurred",
            },
        )

    The general exception handler is particularly important for production: it prevents stack traces from leaking to clients while still logging the full error for debugging.

    Testing the API

    FastAPI makes testing exceptionally straightforward with its built-in TestClient, which is a wrapper around httpx. The entire API can be tested without starting a server.

    Setting Up Tests

    Install pytest if it is not already present:

    pip install pytest httpx

    Create tests/test_tasks.py:

    import pytest
    from fastapi.testclient import TestClient
    from sqlalchemy import create_engine
    from sqlalchemy.orm import sessionmaker
    
    from app.main import app
    from app.database import Base, get_db
    
    # Use an in-memory SQLite database for tests
    TEST_DATABASE_URL = "sqlite:///./test.db"
    engine = create_engine(
        TEST_DATABASE_URL,
        connect_args={"check_same_thread": False},
    )
    TestingSessionLocal = sessionmaker(
        autocommit=False, autoflush=False, bind=engine
    )
    
    
    def override_get_db():
        db = TestingSessionLocal()
        try:
            yield db
        finally:
            db.close()
    
    
    # Override the database dependency
    app.dependency_overrides[get_db] = override_get_db
    client = TestClient(app)
    
    
    @pytest.fixture(autouse=True)
    def setup_database():
        """Create tables before each test, drop after."""
        Base.metadata.create_all(bind=engine)
        yield
        Base.metadata.drop_all(bind=engine)
    
    
    def test_read_root():
        response = client.get("/")
        assert response.status_code == 200
        assert response.json() == {"message": "Welcome to the Task Manager API"}
    
    
    def test_create_task():
        response = client.post(
            "/tasks",
            json={
                "title": "Test Task",
                "description": "A test task",
                "priority": 3,
            },
        )
        assert response.status_code == 201
        data = response.json()
        assert data["title"] == "Test Task"
        assert data["description"] == "A test task"
        assert data["priority"] == 3
        assert data["status"] == "pending"
        assert "id" in data
        assert "created_at" in data
    
    
    def test_create_task_validation_error():
        response = client.post(
            "/tasks",
            json={"title": "", "priority": 10},  # Empty title, priority too high
        )
        assert response.status_code == 422
    
    
    def test_get_task():
        # Create a task first
        create_response = client.post(
            "/tasks", json={"title": "Find me"}
        )
        task_id = create_response.json()["id"]
    
        # Retrieve it
        response = client.get(f"/tasks/{task_id}")
        assert response.status_code == 200
        assert response.json()["title"] == "Find me"
    
    
    def test_get_task_not_found():
        response = client.get("/tasks/99999")
        assert response.status_code == 404
    
    
    def test_update_task():
        # Create a task
        create_response = client.post(
            "/tasks", json={"title": "Original Title"}
        )
        task_id = create_response.json()["id"]
    
        # Update it
        response = client.put(
            f"/tasks/{task_id}",
            json={"title": "Updated Title", "status": "in_progress"},
        )
        assert response.status_code == 200
        assert response.json()["title"] == "Updated Title"
        assert response.json()["status"] == "in_progress"
    
    
    def test_delete_task():
        # Create a task
        create_response = client.post(
            "/tasks", json={"title": "Delete me"}
        )
        task_id = create_response.json()["id"]
    
        # Delete it
        response = client.delete(f"/tasks/{task_id}")
        assert response.status_code == 204
    
        # Verify it is gone
        response = client.get(f"/tasks/{task_id}")
        assert response.status_code == 404
    
    
    def test_list_tasks_with_filter():
        # Create tasks with different statuses
        client.post(
            "/tasks", json={"title": "Task 1", "status": "pending"}
        )
        client.post(
            "/tasks", json={"title": "Task 2", "status": "completed"}
        )
        client.post(
            "/tasks", json={"title": "Task 3", "status": "pending"}
        )
    
        # Filter by status
        response = client.get("/tasks?status=pending")
        assert response.status_code == 200
        tasks = response.json()
        assert len(tasks) == 2
        assert all(t["status"] == "pending" for t in tasks)
    
    
    def test_list_tasks_pagination():
        # Create 5 tasks
        for i in range(5):
            client.post("/tasks", json={"title": f"Task {i}"})
    
        # Get first page
        response = client.get("/tasks?skip=0&limit=2")
        assert response.status_code == 200
        assert len(response.json()) == 2
    
        # Get second page
        response = client.get("/tasks?skip=2&limit=2")
        assert response.status_code == 200
        assert len(response.json()) == 2

    Run the tests:

    pytest tests/ -v
    Key Takeaway: The dependency-injection system renders testing clean: the real database is replaced by a test database with a single line (app.dependency_overrides[get_db] = override_get_db). No mocking, no patching, no test doubles. This is one of FastAPI’s most underappreciated features.

    Deployment

    The following section describes taking the API from development to production.

    Running in Production with Gunicorn

    In production, Uvicorn should be run behind Gunicorn for process management and multi-worker support:

    pip install gunicorn
    
    # Run with 4 worker processes
    gunicorn app.main:app \
        --workers 4 \
        --worker-class uvicorn.workers.UvicornWorker \
        --bind 0.0.0.0:8000 \
        --access-logfile - \
        --error-logfile -

    A useful rule of thumb for the number of workers is (2 x CPU cores) + 1. For a 2-core server, five workers are appropriate.

    Docker Containerisation

    A Dockerfile is used to containerise the FastAPI application. For a thorough treatment of Docker from development to production, including multi-stage builds and Docker Compose, see the related Docker containers guide for development and production:

    # Use the official Python slim image
    FROM python:3.11-slim
    
    # Set working directory
    WORKDIR /app
    
    # Install dependencies first (leverages Docker caching)
    COPY requirements.txt .
    RUN pip install --no-cache-dir -r requirements.txt
    
    # Copy application code
    COPY app/ ./app/
    
    # Create non-root user for security
    RUN adduser --disabled-password --gecos "" appuser
    USER appuser
    
    # Expose port
    EXPOSE 8000
    
    # Run with Gunicorn in production
    CMD ["gunicorn", "app.main:app", \
         "--workers", "4", \
         "--worker-class", "uvicorn.workers.UvicornWorker", \
         "--bind", "0.0.0.0:8000"]

    And a docker-compose.yml for easy local testing:

    version: "3.8"
    services:
      api:
        build: .
        ports:
          - "8000:8000"
        environment:
          - DATABASE_URL=postgresql://postgres:password@db:5432/taskmanager
          - SECRET_KEY=your-production-secret-key
        depends_on:
          - db
    
      db:
        image: postgres:16
        environment:
          - POSTGRES_DB=taskmanager
          - POSTGRES_PASSWORD=password
        volumes:
          - postgres_data:/var/lib/postgresql/data
        ports:
          - "5432:5432"
    
    volumes:
      postgres_data:

    Build and run:

    docker-compose up --build

    Cloud Deployment Options

    Several cloud-deployment options are available, depending on scale and budget:

    • AWS Lightsail or EC2 — full control, appropriate for small to medium deployments
    • Google Cloud Run — serverless containers, scaling to zero, pay-per-request pricing
    • Railway or Render — simple PaaS options with generous free tiers
    • AWS Lambda with Mangum — serverless deployment using the Mangum ASGI adapter

    Best Practices

    As an API grows beyond a simple tutorial, the following practices keep the codebase maintainable and the API reliable.

    Project Structure for Larger Applications

    For larger applications, the code should be organised using FastAPI’s router system:

    app/
    ├── __init__.py
    ├── main.py                 # App factory, middleware, startup events
    ├── config.py               # Settings via pydantic-settings
    ├── database.py             # DB engine, session, base
    ├── dependencies.py         # Shared dependencies (auth, db session)
    ├── models/                 # SQLAlchemy models
    │   ├── __init__.py
    │   ├── task.py
    │   └── user.py
    ├── schemas/                # Pydantic schemas
    │   ├── __init__.py
    │   ├── task.py
    │   └── user.py
    ├── routers/                # API route handlers
    │   ├── __init__.py
    │   ├── tasks.py
    │   └── users.py
    ├── services/               # Business logic
    │   ├── __init__.py
    │   ├── task_service.py
    │   └── user_service.py
    └── middleware/              # Custom middleware
        ├── __init__.py
        └── logging.py

    Each router file has the following structure:

    # app/routers/tasks.py
    from fastapi import APIRouter, Depends
    from sqlalchemy.orm import Session
    
    from app.dependencies import get_db, get_current_user
    from app.schemas.task import TaskCreate, TaskResponse
    from app.services import task_service
    
    router = APIRouter(
        prefix="/tasks",
        tags=["tasks"],
        dependencies=[Depends(get_current_user)],
    )
    
    
    @router.get("/", response_model=list[TaskResponse])
    def list_tasks(db: Session = Depends(get_db)):
        return task_service.get_all_tasks(db)

    The main file then includes the routers:

    # app/main.py
    from fastapi import FastAPI
    from app.routers import tasks, users
    
    app = FastAPI(title="Task Manager API")
    app.include_router(tasks.router)
    app.include_router(users.router)

    Environment Variables with Pydantic Settings

    # app/config.py
    from pydantic_settings import BaseSettings
    from functools import lru_cache
    
    
    class Settings(BaseSettings):
        database_url: str = "sqlite:///./tasks.db"
        secret_key: str = "change-me-in-production"
        api_key: str = "change-me-in-production"
        debug: bool = False
        allowed_origins: list[str] = ["http://localhost:3000"]
    
        class Config:
            env_file = ".env"
    
    
    @lru_cache
    def get_settings() -> Settings:
        return Settings()
    
    
    # Usage in endpoints:
    # settings = Depends(get_settings)

    API Versioning

    # Version via URL prefix
    v1_router = APIRouter(prefix="/api/v1")
    v2_router = APIRouter(prefix="/api/v2")
    
    app.include_router(v1_router)
    app.include_router(v2_router)

    Rate Limiting

    For rate limiting, the slowapi library integrates cleanly with FastAPI:

    pip install slowapi
    from slowapi import Limiter, _rate_limit_exceeded_handler
    from slowapi.util import get_remote_address
    from slowapi.errors import RateLimitExceeded
    
    limiter = Limiter(key_func=get_remote_address)
    app.state.limiter = limiter
    app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
    
    
    @app.get("/tasks")
    @limiter.limit("60/minute")
    def list_tasks(request: Request):
        ...
    Key Takeaway: FastAPI’s modular architecture — routers, dependency injection, Pydantic settings — makes it straightforward to scale from a single-file prototype to a well-structured production application. The appropriate approach is to begin simply and refactor as the project grows.

    Concluding Observations

    This guide has covered substantial ground. Beginning from a simple “Hello World” endpoint, a complete task-management API has been constructed with CRUD operations, database persistence using SQLAlchemy, authentication with both API keys and JWT tokens, CORS support, custom middleware, comprehensive tests, and a production deployment configured with Docker.

    What distinguishes FastAPI is not any single feature; it is how all of its features work together seamlessly. Type hints drive validation, documentation, and editor support simultaneously. Dependency injection keeps code testable and modular. Pydantic models serve as the single source of truth for data contracts. The async foundation permits the API to handle serious traffic without complex optimisation.

    The components constructed in this guide are summarised below:

    Component Technology Purpose
    Framework FastAPI API routing, validation, docs
    Server Uvicorn / Gunicorn ASGI server for production
    Validation Pydantic Request/response data models
    Database SQLAlchemy + SQLite Persistent data storage
    Authentication JWT + API Keys Secure endpoint access
    Testing pytest + TestClient Automated API testing
    Deployment Docker + Gunicorn Containerized production setup

     

    For teams seeking still more performance from the API layer, writing performance-critical endpoints as native extensions is becoming practical owing to Python and Rust interoperability via PyO3. For developers migrating from Flask, the transition to FastAPI is remarkably smooth: most concepts map directly, and type safety, auto-generated documentation, and improved performance are gained without additional effort. For developers migrating from Django REST Framework, the lighter weight and more explicit architecture, with comparable functionality, are likely to be appreciated.

    The Python web ecosystem has evolved significantly, and FastAPI represents the present state of the art. Whether the project is a simple microservice, a complex multi-tenant SaaS, or a high-performance data API, FastAPI provides the tools to build it cleanly and efficiently.

    As the codebase grows, following clean-code principles and using Git best practices for professional developers will keep the API maintainable. Building something real is the appropriate next step. The task manager constructed here can be extended with additional features — tags, due dates, user assignments, notifications — and deployed. The most effective way to learn a framework is to ship something with it.

    References

  • How to Install and Use OpenClaw on Windows 11: A Complete Setup Guide

    Summary

    What this post covers: Three end-to-end installation paths — WSL2, native Windows + Conda, and Docker — for running the OpenClaw robotic-manipulation framework on Windows 11, including GPU acceleration, your first training run, and Windows-specific troubleshooting.

    Key insights:

    • WSL2 with Ubuntu 22.04 is the recommended approach for most Windows 11 users — it delivers near-native Linux performance, supports the full CUDA toolkit, and avoids the dependency rot that plagues native Conda installs of MuJoCo on Windows.
    • Native Windows + Conda works but requires specific pinned versions of MuJoCo bindings and Visual C++ build tools; expect to spend extra time on environment debugging compared to WSL2.
    • Docker offers the most reproducible setup but adds GPU passthrough complexity (NVIDIA Container Toolkit on WSL2 backend) and slower disk I/O for large training checkpoints.
    • GPU acceleration through CUDA delivers roughly 10–50x training-throughput speedups over CPU-only runs; verifying nvidia-smi visibility inside WSL2 before installing PyTorch saves hours of confused debugging.
    • The most common Windows-specific failures are X11/display issues for the MuJoCo viewer (fixable via WSLg or VcXsrv), path conflicts between Windows and WSL2 home directories, and DLL load errors from mismatched CUDA versions.

    Main topics: Introduction, System Requirements, Method 1: WSL2 (Recommended Approach), Method 2: Native Windows with Conda, Method 3: Docker on Windows, Running Your First Experiments, Training Your First Policy, GPU Acceleration and Performance Tips, Troubleshooting Common Windows Issues, Integration with VS Code, Next Steps and Resources, Final Thoughts, References.

    Introduction

    An often-overlooked fact: more than 70 percent of AI researchers and robotics students operate Windows as their primary operating system, yet almost every serious robotics simulation framework ships with Linux-first documentation and Linux-only installation scripts. Anyone who has examined a GitHub README full of apt-get commands and wondered whether a Windows 11 machine could participate is familiar with the difficulty.

    OpenClaw is an open-source robotic manipulation framework designed for AI research. It provides a rich set of simulated environments for dexterous manipulation tasks, including robotic hands grasping objects, assembling parts and performing precise movements that test the limits of reinforcement learning. Built on top of MuJoCo, which is now free and open source, and compatible with widely used RL libraries such as Stable Baselines3, OpenClaw has rapidly become a preferred toolkit for researchers working on manipulation policies.

    The complication is that, like most robotics frameworks, OpenClaw was developed with Linux in mind. The official documentation assumes Ubuntu, the CI pipelines test on Linux, and many convenience scripts are written in bash. For the Windows 11 user, getting OpenClaw running can feel like assembling a puzzle with several missing pieces.

    This guide addresses that gap. The following sections present three complete installation methods, WSL2, native Windows with Conda, and Docker, each with full command-by-command instructions. By the end, the reader will have OpenClaw running on a Windows 11 machine, will have trained an initial manipulation policy, and will be able to visualise robotic simulations with full GPU acceleration. A Linux dual-boot is not required.

    Windows 11 OpenClaw Software Stack Windows 11 WSL2 (Windows Subsystem for Linux) Ubuntu 22.04 + CUDA Toolkit MuJoCo Physics Engine OpenClaw

    Key Takeaway: Working with current robotics AI frameworks does not require abandoning Windows 11. With WSL2, Conda or Docker, OpenClaw can be run with full GPU acceleration directly from a Windows desktop.

    System Requirements

    Before proceeding to installation, the machine should be verified as adequate to the task. OpenClaw runs physics simulations and neural network training simultaneously, which requires substantial computational capacity. The required specifications are summarised below.

    Hardware Requirements

    Component Minimum Recommended
    OS Windows 11 21H2 Windows 11 22H2 or later
    GPU NVIDIA GTX 1070 (8GB VRAM) NVIDIA RTX 3060 12GB or better
    RAM 16 GB 32 GB or more
    Storage 50 GB free (SSD) 100 GB+ free (NVMe SSD)
    CPU Intel i5 / AMD Ryzen 5 Intel i7/i9 or AMD Ryzen 7/9
    Python 3.9 3.10 or 3.11

     

    Software Prerequisites

    Regardless of which installation method is selected, the following items should be prepared in advance.

    • NVIDIA GPU drivers: Version 525.0 or later (download from nvidia.com/drivers)
    • Windows Terminal: Pre-installed on Windows 11, but grab it from the Microsoft Store if missing
    • Git for Windows: Download from git-scm.com
    • A text editor or IDE: VS Code is strongly recommended

    To check the current NVIDIA driver version, open PowerShell and run the following.

    nvidia-smi

    The output should display the driver version and CUDA version. If the command fails, NVIDIA drivers should be installed or updated before proceeding.

    Caution: AMD GPUs are not supported for CUDA-accelerated training. Users with AMD GPUs may follow this guide for CPU-only training, but performance will be substantially slower. ROCm support on Windows remains limited for most ML frameworks.

    Method 1: WSL2 (Recommended Approach)

    WSL2 (Windows Subsystem for Linux 2) is the preferred mechanism for running Linux-native tools on Windows. It provides a real Linux kernel, full system call compatibility and, critically for this purpose, native GPU passthrough. NVIDIA GPUs therefore operate inside WSL2 at near-native performance. For OpenClaw, this is the recommended path because it offers complete Linux compatibility without the operational difficulties of dual-booting.

    WSL2 Installation Workflow Prerequisites GPU Driver, Git WSL2 + Ubuntu wsl –install CUDA + MuJoCo Toolkit & Physics OpenClaw Install pip install -e. Verify & Run python -c import Step 1 Step 2 Steps 3–4 Step 5 Steps 6–7

    Step 1: Enable and Install WSL2

    Open PowerShell as Administrator and run:

    # Install WSL2 with Ubuntu 22.04 (default)
    wsl --install -d Ubuntu-22.04
    
    # If WSL is already installed, make sure it's version 2
    wsl --set-default-version 2
    
    # Verify installation
    wsl --list --verbose

    After installation completes, restart the computer. When Ubuntu is opened from the Start menu for the first time, the user is prompted to create a username and password. A simple credential should be chosen, since it will be entered frequently for sudo commands.

    # Verify WSL2 is running correctly
    wsl --list --verbose
    
    # Expected output:
    #   NAME            STATE           VERSION
    # * Ubuntu-22.04    Running         2

    Step 2: Update the System and Install Base Dependencies

    Open the Ubuntu terminal (either from the Start menu or by typing wsl in PowerShell) and run the following commands.

    # Update package lists and upgrade existing packages
    sudo apt update && sudo apt upgrade -y
    
    # Install essential build tools and libraries
    sudo apt install -y \
        build-essential \
        cmake \
        git \
        wget \
        curl \
        unzip \
        pkg-config \
        libgl1-mesa-dev \
        libglu1-mesa-dev \
        libglew-dev \
        libosmesa6-dev \
        libglfw3-dev \
        libxrandr-dev \
        libxinerama-dev \
        libxcursor-dev \
        libxi-dev \
        patchelf \
        python3-dev \
        python3-pip \
        python3-venv \
        software-properties-common

    Step 3: Install NVIDIA CUDA Toolkit in WSL2

    This is the step that most often causes difficulty. The key point is that NVIDIA drivers must not be installed inside WSL2. The Windows host drivers handle GPU communication. Only the CUDA toolkit is required inside WSL2.

    Caution: The nvidia-driver package should NOT be installed inside WSL2. The Windows host driver is shared with WSL2 automatically. Installing a Linux driver inside WSL2 will disable GPU support.
    # Add the CUDA repository key and repo
    wget https://developer.download.nvidia.com/compute/cuda/repos/wsl-ubuntu/x86_64/cuda-wsl-ubuntu.pin
    sudo mv cuda-wsl-ubuntu.pin /etc/apt/preferences.d/cuda-repository-pin-600
    wget https://developer.download.nvidia.com/compute/cuda/12.4.0/local_installers/cuda-repo-wsl-ubuntu-12-4-local_12.4.0-1_amd64.deb
    sudo dpkg -i cuda-repo-wsl-ubuntu-12-4-local_12.4.0-1_amd64.deb
    sudo cp /var/cuda-repo-wsl-ubuntu-12-4-local/cuda-*-keyring.gpg /usr/share/keyrings/
    sudo apt update
    sudo apt install -y cuda-toolkit-12-4
    
    # Add CUDA to your PATH
    echo 'export PATH=/usr/local/cuda-12.4/bin:$PATH' >> ~/.bashrc
    echo 'export LD_LIBRARY_PATH=/usr/local/cuda-12.4/lib64:$LD_LIBRARY_PATH' >> ~/.bashrc
    source ~/.bashrc
    
    # Verify CUDA installation
    nvcc --version
    nvidia-smi

    Both commands should succeed. nvidia-smi displays GPU information drawn from the Windows host driver, and nvcc --version confirms that the CUDA compiler is installed.

    Step 4: Install MuJoCo

    OpenClaw uses MuJoCo as its physics simulation backend. Since DeepMind released MuJoCo as free and open-source software, installation has become substantially simpler.

    # Download and extract MuJoCo
    mkdir -p ~/.mujoco
    wget https://github.com/google-deepmind/mujoco/releases/download/3.1.3/mujoco-3.1.3-linux-x86_64.tar.gz
    tar -xzf mujoco-3.1.3-linux-x86_64.tar.gz -C ~/.mujoco/
    mv ~/.mujoco/mujoco-3.1.3 ~/.mujoco/mujoco313
    
    # Set environment variables
    echo 'export MUJOCO_PATH=$HOME/.mujoco/mujoco313' >> ~/.bashrc
    echo 'export LD_LIBRARY_PATH=$MUJOCO_PATH/lib:$LD_LIBRARY_PATH' >> ~/.bashrc
    source ~/.bashrc
    
    # Test MuJoCo binary
    $MUJOCO_PATH/bin/simulate $MUJOCO_PATH/model/humanoid/humanoid.xml &
    Tip: If the MuJoCo viewer opens and displays an animated humanoid, GPU passthrough and graphics rendering are functioning correctly inside WSL2.

    Step 5: Clone and Install OpenClaw

    The next step is to create a dedicated Python virtual environment and install OpenClaw from source.

    # Create a workspace directory
    mkdir -p ~/robotics && cd ~/robotics
    
    # Clone the OpenClaw repository
    git clone https://github.com/openclaw-project/openclaw.git
    cd openclaw
    
    # Create and activate a Python virtual environment
    python3 -m venv venv
    source venv/bin/activate
    
    # Upgrade pip and install build tools
    pip install --upgrade pip setuptools wheel
    
    # Install PyTorch with CUDA support
    pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu124
    
    # Install MuJoCo Python bindings
    pip install mujoco==3.1.3
    
    # Install OpenClaw and all dependencies
    pip install -e ".[all]"
    
    # Alternatively, install from requirements if available
    # pip install -r requirements.txt
    # pip install -e .

    Verify that the installation completed successfully.

    # Verify PyTorch CUDA support
    python -c "import torch; print(f'PyTorch: {torch.__version__}'); print(f'CUDA available: {torch.cuda.is_available()}'); print(f'GPU: {torch.cuda.get_device_name(0) if torch.cuda.is_available() else \"N/A\"}')"
    
    # Verify MuJoCo
    python -c "import mujoco; print(f'MuJoCo version: {mujoco.__version__}')"
    
    # Verify OpenClaw
    python -c "import openclaw; print(f'OpenClaw loaded successfully')"

    Step 6: Set Up GUI Forwarding for Visualization

    Windows 11 ships with WSLg (Windows Subsystem for Linux GUI), which causes graphical applications to operate transparently in most cases. On Windows 11 22H2 or later, GUI forwarding should be automatic. The setup can be verified as follows.

    # Test GUI display — this should open a small window
    sudo apt install -y x11-apps
    xclock &
    
    # If xclock shows a clock window, WSLg is working.
    # If not, make sure WSL is up to date:
    # (Run this in PowerShell, not WSL)
    # wsl --update

    If WSLg is not functioning, an X server can be used as a fallback.

    # Fallback: Set DISPLAY for manual X server (VcXsrv or X410)
    # Only needed if WSLg is not working
    echo 'export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk "{print \$2}"):0' >> ~/.bashrc
    echo 'export LIBGL_ALWAYS_INDIRECT=0' >> ~/.bashrc
    source ~/.bashrc

    Step 7: Run Your First OpenClaw Environment

    # Make sure you're in the OpenClaw directory with venv activated
    cd ~/robotics/openclaw
    source venv/bin/activate
    
    # Run the demo script to verify everything works
    python -m openclaw.demo --env GraspCube-v1 --render
    
    # Or run a minimal test script
    python -c "
    import openclaw
    import numpy as np
    
    env = openclaw.make('GraspCube-v1', render_mode='human')
    obs, info = env.reset()
    print(f'Observation space: {env.observation_space.shape}')
    print(f'Action space: {env.action_space.shape}')
    
    for step in range(100):
        action = env.action_space.sample()
        obs, reward, terminated, truncated, info = env.step(action)
        if terminated or truncated:
            obs, info = env.reset()
    
    env.close()
    print('Environment test completed successfully!')
    "

    If a simulation window appears in which a robotic hand attempts to grasp a cube, even clumsily, the installation is functioning correctly. OpenClaw is now installed on Windows 11 via WSL2.

    Method 2: Native Windows with Conda

    Users who prefer to remain entirely within the Windows ecosystem without WSL2 may install OpenClaw natively using Conda. The approach functions but carries certain caveats: some features may require additional configuration, and Windows-specific path issues may arise. For many use cases, however, it works reliably.

    Step 1: Install Miniconda

    Download and install Miniconda from docs.conda.io. Select the Windows 64-bit installer. During installation:

    • install for “Just Me” (recommended);
    • check “Add Miniconda to my PATH” (despite the warning, this simplifies subsequent steps);
    • check “Register Miniconda as the default Python”.

    Open a new Anaconda Prompt or PowerShell session and verify the installation.

    conda --version
    # Should output: conda 24.x.x or later

    Step 2: Create the Conda Environment

    # Create a new environment with Python 3.10
    conda create -n openclaw python=3.10 -y
    conda activate openclaw
    
    # Install PyTorch with CUDA support via conda
    conda install pytorch torchvision torchaudio pytorch-cuda=12.4 -c pytorch -c nvidia -y
    
    # Verify CUDA is available
    python -c "import torch; print(torch.cuda.is_available())"

    Step 3: Install MuJoCo for Windows

    # Install MuJoCo Python package
    pip install mujoco==3.1.3
    
    # Download the MuJoCo binary release for Windows
    # Create directory: C:\Users\YourName\.mujoco\
    # Download from: https://github.com/google-deepmind/mujoco/releases
    # Extract mujoco-3.1.3-windows-x86_64.zip to C:\Users\YourName\.mujoco\mujoco313
    
    # Set environment variables (PowerShell)
    [Environment]::SetEnvironmentVariable("MUJOCO_PATH", "$env:USERPROFILE\.mujoco\mujoco313", "User")
    [Environment]::SetEnvironmentVariable("PATH", "$env:PATH;$env:USERPROFILE\.mujoco\mujoco313\bin", "User")
    
    # Verify
    python -c "import mujoco; print(mujoco.__version__)"

    Step 4: Install OpenClaw

    # Clone the repository
    cd %USERPROFILE%\Documents
    git clone https://github.com/openclaw-project/openclaw.git
    cd openclaw
    
    # Install OpenClaw
    pip install -e ".[all]"
    
    # If you encounter build errors, try installing dependencies separately:
    pip install numpy scipy gymnasium stable-baselines3 tensorboard
    pip install -e .

    Step 5: Handle Windows-Specific Issues

    Windows paths use backslashes, which can create problems with Linux-oriented Python packages. The common fixes are as follows.

    # Fix 1: If OpenClaw has hardcoded Linux paths, set this environment variable
    set OPENCLAW_ASSET_DIR=%cd%\assets
    
    # Fix 2: For path separator issues in config files, use raw strings in Python
    # Instead of: path = "C:\Users\name\data"
    # Use:        path = r"C:\Users\name\data"
    # Or:         path = "C:/Users/name/data"  (forward slashes work in Python)
    
    # Fix 3: Long path support (PowerShell as Admin)
    New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" `
        -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force
    
    # Fix 4: If you get DLL errors, install Visual C++ Redistributable
    # Download from: https://aka.ms/vs/17/release/vc_redist.x64.exe
    Tip: If a FileNotFoundError related to asset files arises, check whether the framework uses os.path.join() correctly. Some robotics frameworks assume a forward-slash path separator. Setting the OPENCLAW_ASSET_DIR environment variable with forward slashes often resolves these issues.

    Step 6: Test the Installation

    conda activate openclaw
    
    python -c "
    import openclaw
    import torch
    
    print(f'OpenClaw loaded')
    print(f'PyTorch: {torch.__version__}')
    print(f'CUDA: {torch.cuda.is_available()}')
    if torch.cuda.is_available():
        print(f'GPU: {torch.cuda.get_device_name(0)}')
    
    env = openclaw.make('GraspCube-v1', render_mode='human')
    obs, info = env.reset()
    print(f'Environment created: obs shape = {obs.shape}')
    env.close()
    print('All good!')
    "

    Method 3: Docker on Windows

    Docker provides the cleanest and most reproducible installation. All components run in an isolated container, which prevents accidental pollution of the system Python environment or CUDA versions. The trade-off is somewhat more involved setup for GPU passthrough and GUI forwarding.

    Step 1: Install Docker Desktop

    Download Docker Desktop from docker.com. During installation, ensure that “Use WSL 2 instead of Hyper-V” is selected as the backend. After installation:

    # Verify Docker is working (PowerShell)
    docker --version
    docker run hello-world
    
    # Enable GPU support — install NVIDIA Container Toolkit
    # In your WSL2 Ubuntu terminal:
    distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
    curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
    curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | \
        sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
        sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
    sudo apt update
    sudo apt install -y nvidia-container-toolkit
    sudo nvidia-ctk runtime configure --runtime=docker
    sudo systemctl restart docker

    Verify GPU access from Docker.

    docker run --rm --gpus all nvidia/cuda:12.4.0-base-ubuntu22.04 nvidia-smi

    If the GPU is listed in the output, Docker GPU passthrough is functioning.

    Step 2: Create the OpenClaw Dockerfile

    Create a file named Dockerfile.openclaw in the working directory.

    # Dockerfile.openclaw
    FROM nvidia/cuda:12.4.0-devel-ubuntu22.04
    
    ENV DEBIAN_FRONTEND=noninteractive
    ENV PYTHONUNBUFFERED=1
    
    # Install system dependencies
    RUN apt-get update && apt-get install -y \
        build-essential cmake git wget curl unzip \
        python3.10 python3.10-venv python3.10-dev python3-pip \
        libgl1-mesa-dev libglu1-mesa-dev libglew-dev \
        libosmesa6-dev libglfw3-dev patchelf \
        xvfb x11-utils \
        && rm -rf /var/lib/apt/lists/*
    
    # Set Python 3.10 as default
    RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.10 1
    RUN update-alternatives --install /usr/bin/python python /usr/bin/python3.10 1
    
    # Install MuJoCo
    RUN mkdir -p /root/.mujoco && \
        wget -q https://github.com/google-deepmind/mujoco/releases/download/3.1.3/mujoco-3.1.3-linux-x86_64.tar.gz && \
        tar -xzf mujoco-3.1.3-linux-x86_64.tar.gz -C /root/.mujoco/ && \
        mv /root/.mujoco/mujoco-3.1.3 /root/.mujoco/mujoco313 && \
        rm mujoco-3.1.3-linux-x86_64.tar.gz
    
    ENV MUJOCO_PATH=/root/.mujoco/mujoco313
    ENV LD_LIBRARY_PATH=$MUJOCO_PATH/lib:$LD_LIBRARY_PATH
    
    # Create workspace
    WORKDIR /workspace
    
    # Install Python packages
    RUN pip install --upgrade pip setuptools wheel && \
        pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu124 && \
        pip install mujoco==3.1.3
    
    # Clone and install OpenClaw
    RUN git clone https://github.com/openclaw-project/openclaw.git && \
        cd openclaw && \
        pip install -e ".[all]"
    
    # Default command
    CMD ["/bin/bash"]

    Step 3: Build and Run the Container

    # Build the Docker image (this takes 10-20 minutes)
    docker build -f Dockerfile.openclaw -t openclaw:latest .
    
    # Run with GPU support and volume mount for saving experiments
    docker run -it --gpus all \
        -v ${PWD}/experiments:/workspace/experiments \
        -v ${PWD}/configs:/workspace/configs \
        --name openclaw-dev \
        openclaw:latest
    
    # For GUI support (renders to a virtual display, saves videos)
    docker run -it --gpus all \
        -e DISPLAY=$DISPLAY \
        -v /tmp/.X11-unix:/tmp/.X11-unix \
        -v ${PWD}/experiments:/workspace/experiments \
        --name openclaw-gui \
        openclaw:latest

    For headless rendering (no display), Xvfb may be used.

    # Inside the container
    Xvfb :1 -screen 0 1024x768x24 &
    export DISPLAY=:1
    
    # Now rendering commands will work headlessly
    python -m openclaw.demo --env GraspCube-v1 --record-video output.mp4

    Step 4: Daily Workflow with Docker

    # Start an existing stopped container
    docker start -ai openclaw-dev
    
    # Run a training job in the background
    docker exec -d openclaw-dev python -m openclaw.train \
        --config configs/grasp_cube.yaml \
        --output experiments/run_001
    
    # Check training logs
    docker exec openclaw-dev tail -f experiments/run_001/train.log
    
    # Copy results out of the container
    docker cp openclaw-dev:/workspace/experiments/run_001 ./local_results/
    Key Takeaway: Docker is well suited to reproducibility. Once the image builds successfully, it can be shared with collaborators and guarantees identical environments. The overhead is minimal: GPU performance in Docker matches native performance within 1 to 2 percent.

    Running Your First Experiments

    With OpenClaw installed via any of the methods above, the framework’s capabilities can now be explored. OpenClaw ships with several pre-built environments covering a range of manipulation tasks.

    Exploring Available Environments

    import openclaw
    
    # List all registered environments
    envs = openclaw.list_environments()
    for env_name in envs:
        print(env_name)

    Typical environments include the following tasks.

    Environment Task Description Difficulty
    GraspCube-v1 Pick up a cube with a dexterous hand Beginner
    RotateBlock-v1 In-hand rotation of a block to target orientation Intermediate
    StackBlocks-v1 Stack two blocks on top of each other Advanced
    InsertPeg-v1 Insert a peg into a hole with tight tolerance Advanced
    OpenDrawer-v1 Pull open a drawer using the handle Intermediate

     

    Loading and Interacting with an Environment

    import openclaw
    import numpy as np
    
    # Create the environment with visual rendering
    env = openclaw.make('GraspCube-v1', render_mode='human')
    
    # Reset and inspect the observation
    obs, info = env.reset(seed=42)
    print(f"Observation shape: {obs.shape}")
    print(f"Observation range: [{obs.min():.3f}, {obs.max():.3f}]")
    print(f"Action space: {env.action_space}")
    print(f"Action range: [{env.action_space.low.min():.1f}, {env.action_space.high.max():.1f}]")
    
    # Run random actions for 500 steps
    total_reward = 0
    for step in range(500):
        action = env.action_space.sample()
        obs, reward, terminated, truncated, info = env.step(action)
        total_reward += reward
    
        if terminated or truncated:
            print(f"Episode ended at step {step}, total reward: {total_reward:.2f}")
            obs, info = env.reset()
            total_reward = 0
    
    env.close()

    Recording Simulation Videos

    For sharing results or debugging policies, recording videos is essential.

    import openclaw
    from gymnasium.wrappers import RecordVideo
    
    # Wrap the environment with video recording
    env = openclaw.make('GraspCube-v1', render_mode='rgb_array')
    env = RecordVideo(env, video_folder='./videos', episode_trigger=lambda e: True)
    
    obs, info = env.reset()
    for step in range(1000):
        action = env.action_space.sample()
        obs, reward, terminated, truncated, info = env.step(action)
        if terminated or truncated:
            obs, info = env.reset()
    
    env.close()
    print("Video saved to ./videos/")

    Evaluating a Pre-trained Model

    OpenClaw typically includes pre-trained checkpoints for benchmarking.

    from stable_baselines3 import PPO
    import openclaw
    
    # Load a pre-trained model (if available in the repo)
    model = PPO.load("pretrained/grasp_cube_ppo.zip")
    
    env = openclaw.make('GraspCube-v1', render_mode='human')
    obs, info = env.reset()
    
    total_reward = 0
    episode_count = 0
    
    for step in range(5000):
        action, _states = model.predict(obs, deterministic=True)
        obs, reward, terminated, truncated, info = env.step(action)
        total_reward += reward
    
        if terminated or truncated:
            episode_count += 1
            print(f"Episode {episode_count}: reward = {total_reward:.2f}")
            total_reward = 0
            obs, info = env.reset()
    
    env.close()
    print(f"Evaluated {episode_count} episodes")

    Understanding the Config System

    OpenClaw uses YAML configuration files to define environments, training hyperparameters and experiment settings. This simplifies reproduction of results and adjustment of parameters without modifying code.

    # Example: configs/grasp_cube.yaml
    environment:
      name: GraspCube-v1
      max_episode_steps: 200
      reward_type: dense  # 'dense' or 'sparse'
      obs_type: state     # 'state', 'pixels', or 'state+pixels'
    
    robot:
      hand_type: shadow_hand
      control_mode: position  # 'position', 'velocity', or 'torque'
      action_scale: 0.05
    
    object:
      type: cube
      size: [0.04, 0.04, 0.04]
      mass: 0.1
      friction: [1.0, 0.005, 0.0001]
    
    simulation:
      physics_timestep: 0.002
      control_timestep: 0.02  # 50 Hz control
      num_substeps: 10
      gravity: [0, 0, -9.81]

    Training Your First Policy

    The next step is training a neural network to control a robotic hand. The following example uses Stable Baselines3’s PPO (Proximal Policy Optimisation) algorithm, which is widely used in robotic manipulation research.

    Setting Up the Training Script

    Create a file called train_grasp.py.

    """
    Train a PPO agent to grasp a cube using OpenClaw.
    """
    import os
    import argparse
    from datetime import datetime
    
    import openclaw
    from stable_baselines3 import PPO
    from stable_baselines3.common.vec_env import SubprocVecEnv, VecMonitor
    from stable_baselines3.common.callbacks import (
        EvalCallback,
        CheckpointCallback,
        CallbackList,
    )
    
    def make_env(env_id, rank, seed=0):
        """Create a wrapped environment for vectorized training."""
        def _init():
            env = openclaw.make(env_id)
            env.reset(seed=seed + rank)
            return env
        return _init
    
    def main():
        parser = argparse.ArgumentParser()
        parser.add_argument('--env', default='GraspCube-v1', help='Environment ID')
        parser.add_argument('--num-envs', type=int, default=8, help='Parallel envs')
        parser.add_argument('--total-timesteps', type=int, default=2_000_000)
        parser.add_argument('--output-dir', default='./experiments')
        parser.add_argument('--seed', type=int, default=42)
        args = parser.parse_args()
    
        # Create experiment directory
        timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
        exp_dir = os.path.join(args.output_dir, f'{args.env}_{timestamp}')
        os.makedirs(exp_dir, exist_ok=True)
    
        # Create vectorized training environments
        train_envs = SubprocVecEnv([
            make_env(args.env, i, args.seed) for i in range(args.num_envs)
        ])
        train_envs = VecMonitor(train_envs, os.path.join(exp_dir, 'monitor'))
    
        # Create evaluation environment
        eval_env = SubprocVecEnv([make_env(args.env, 0, args.seed + 1000)])
        eval_env = VecMonitor(eval_env)
    
        # Configure PPO
        model = PPO(
            policy='MlpPolicy',
            env=train_envs,
            learning_rate=3e-4,
            n_steps=2048,
            batch_size=256,
            n_epochs=10,
            gamma=0.99,
            gae_lambda=0.95,
            clip_range=0.2,
            ent_coef=0.01,
            vf_coef=0.5,
            max_grad_norm=0.5,
            verbose=1,
            seed=args.seed,
            tensorboard_log=os.path.join(exp_dir, 'tensorboard'),
            device='cuda',
        )
    
        # Set up callbacks
        eval_callback = EvalCallback(
            eval_env,
            best_model_save_path=os.path.join(exp_dir, 'best_model'),
            log_path=os.path.join(exp_dir, 'eval_logs'),
            eval_freq=10_000,
            n_eval_episodes=10,
            deterministic=True,
        )
    
        checkpoint_callback = CheckpointCallback(
            save_freq=50_000,
            save_path=os.path.join(exp_dir, 'checkpoints'),
            name_prefix='ppo_grasp',
        )
    
        callbacks = CallbackList([eval_callback, checkpoint_callback])
    
        # Train!
        print(f"Starting training: {args.total_timesteps} timesteps")
        print(f"Experiment directory: {exp_dir}")
        model.learn(
            total_timesteps=args.total_timesteps,
            callback=callbacks,
            progress_bar=True,
        )
    
        # Save final model
        model.save(os.path.join(exp_dir, 'final_model'))
        print(f"Training complete! Model saved to {exp_dir}")
    
        # Cleanup
        train_envs.close()
        eval_env.close()
    
    if __name__ == '__main__':
        main()

    Launch Training

    # Basic training run
    python train_grasp.py --env GraspCube-v1 --total-timesteps 2000000
    
    # With more parallel environments (faster on multi-core CPUs)
    python train_grasp.py --env GraspCube-v1 --num-envs 16 --total-timesteps 5000000
    
    # For a quick test run
    python train_grasp.py --env GraspCube-v1 --num-envs 4 --total-timesteps 50000

    Monitor Training with TensorBoard

    Open a separate terminal while training is running.

    # Install TensorBoard if not already installed
    pip install tensorboard
    
    # Launch TensorBoard
    tensorboard --logdir ./experiments --port 6006
    
    # Open in your browser: http://localhost:6006

    Key metrics to monitor during training are as follows.

    • ep_rew_mean: Average episode reward—this should generally trend upward
    • ep_len_mean: Average episode length—shorter can mean the agent achieves the goal faster
    • loss/policy_loss: Should decrease and stabilize
    • loss/value_loss: Should decrease over time
    • explained_variance: Should approach 1.0 as training progresses
    Tip: For the GraspCube-v1 task, meaningful improvement should appear within 500,000 to 1 million timesteps. If the reward curve remains completely flat after one million steps, the environment configuration and reward function should be checked. Dense rewards converge substantially faster than sparse rewards for beginners.

    Evaluate Your Trained Agent

    from stable_baselines3 import PPO
    import openclaw
    import numpy as np
    
    # Load the best model from training
    model = PPO.load("experiments/GraspCube-v1_YYYYMMDD_HHMMSS/best_model/best_model")
    
    env = openclaw.make('GraspCube-v1', render_mode='human')
    
    rewards = []
    for episode in range(20):
        obs, info = env.reset()
        episode_reward = 0
        done = False
    
        while not done:
            action, _ = model.predict(obs, deterministic=True)
            obs, reward, terminated, truncated, info = env.step(action)
            episode_reward += reward
            done = terminated or truncated
    
        rewards.append(episode_reward)
        print(f"Episode {episode + 1}: reward = {episode_reward:.2f}")
    
    env.close()
    print(f"\nMean reward: {np.mean(rewards):.2f} +/- {np.std(rewards):.2f}")

    GPU Acceleration and Performance Tips

    Maximising GPU utilisation can substantially accelerate training. The following sections describe verification, optimisation and benchmarking procedures.

    System Architecture: Windows ↔ WSL2 ↔ MuJoCo ↔ OpenClaw Windows 11 Host NVIDIA GPU (CUDA) Display / WSLg GPU Driver v525+ WSL2 / Ubuntu Linux Kernel 5.15+ CUDA Toolkit 12.4 Python 3.10 venv MuJoCo 3.x Physics Simulation OpenGL Rendering Contact Dynamics OpenClaw Gym Environments RL Training (PPO) Policy Evaluation GPU Hardware Linux Layer Sim Engine AI Framework

    CUDA Setup Verification

    # Comprehensive CUDA check script
    python -c "
    import torch
    import subprocess
    
    print('=== CUDA Diagnostics ===')
    print(f'PyTorch version: {torch.__version__}')
    print(f'CUDA available: {torch.cuda.is_available()}')
    print(f'CUDA version (PyTorch): {torch.version.cuda}')
    print(f'cuDNN version: {torch.backends.cudnn.version()}')
    print(f'cuDNN enabled: {torch.backends.cudnn.enabled}')
    
    if torch.cuda.is_available():
        print(f'GPU count: {torch.cuda.device_count()}')
        for i in range(torch.cuda.device_count()):
            props = torch.cuda.get_device_properties(i)
            print(f'  GPU {i}: {props.name}')
            print(f'    Memory: {props.total_mem / 1024**3:.1f} GB')
            print(f'    Compute capability: {props.major}.{props.minor}')
            print(f'    Multi-processors: {props.multi_processor_count}')
    
        # Quick benchmark
        print('\n=== Quick Benchmark ===')
        x = torch.randn(10000, 10000, device='cuda')
        import time
        start = time.time()
        for _ in range(100):
            y = torch.mm(x, x)
        torch.cuda.synchronize()
        elapsed = time.time() - start
        print(f'100x matrix multiply (10000x10000): {elapsed:.2f}s')
        print(f'TFLOPS estimate: {100 * 2 * 10000**3 / elapsed / 1e12:.1f}')
    "

    Optimizing Batch Sizes

    The appropriate batch size depends on the available GPU VRAM. The following table provides a general guideline.

    GPU VRAM Recommended Batch Size Parallel Envs Expected Throughput
    6 GB (RTX 3060) 128 4-8 ~2,000 steps/sec
    8 GB (RTX 3070/4060) 256 8-12 ~3,500 steps/sec
    12 GB (RTX 3060 12GB/4070) 512 12-16 ~5,000 steps/sec
    16 GB+ (RTX 4080/4090) 1024 16-32 ~10,000+ steps/sec

     

    WSL2 vs Native Performance Comparison

    Based on typical benchmarks, the three installation methods compare as follows.

    Metric WSL2 Native Windows Docker (WSL2 backend)
    GPU compute 98-100% of native Linux 95-100% 97-100%
    Disk I/O 60-70% (cross-filesystem) 100% (native NTFS) 50-65% (overlay)
    Linux compatibility Excellent Partial Full
    Setup complexity Medium Low Medium-High
    GUI rendering WSLg (built-in) Native Requires forwarding
    Reproducibility Good Fair Excellent

     

    Key Takeaway: For most users, WSL2 offers the best balance of performance, compatibility and ease of use. Project files should be kept on the Linux filesystem (inside ~/) rather than on /mnt/c/ in order to avoid the disk I/O penalty.

    Memory Management Tips

    # Monitor GPU memory during training
    watch -n 1 nvidia-smi
    
    # In Python, check memory usage:
    import torch
    print(f"Allocated: {torch.cuda.memory_allocated() / 1024**3:.2f} GB")
    print(f"Cached: {torch.cuda.memory_reserved() / 1024**3:.2f} GB")
    
    # Free GPU cache if needed
    torch.cuda.empty_cache()
    
    # Limit WSL2 memory usage by creating .wslconfig
    # Create/edit: C:\Users\YourName\.wslconfig

    Create or edit C:\Users\YourName\.wslconfig to control WSL2’s resource usage.

    [wsl2]
    memory=16GB          # Limit WSL2 RAM (default: 50% of system RAM)
    processors=8         # Limit CPU cores
    swap=8GB             # Swap file size
    localhostForwarding=true

    Multi-GPU Training Setup

    For systems with multiple GPUs, OpenClaw combined with Stable Baselines3 can use them as follows.

    # Check available GPUs
    python -c "
    import torch
    for i in range(torch.cuda.device_count()):
        print(f'GPU {i}: {torch.cuda.get_device_name(i)}')
    "
    
    # To use a specific GPU
    CUDA_VISIBLE_DEVICES=1 python train_grasp.py
    
    # For multi-GPU with data parallelism, modify the training script:
    # model = PPO(..., device='cuda:0')
    # Or use torch.nn.DataParallel for custom architectures

    Troubleshooting Common Windows Issues

    If the preceding steps have been completed, OpenClaw is most likely running. Robotics simulation frameworks are complex systems, however, and failures do occur. The most common issues and their solutions are summarised below.

    Error Cause Solution
    CUDA not found in WSL2 Windows NVIDIA driver too old or CUDA toolkit not installed in WSL2 Update Windows NVIDIA driver to 525+, install cuda-toolkit-12-4 in WSL2 (not the full driver)
    GLFWError: API unavailable MuJoCo cannot create an OpenGL context Install libosmesa6-dev, set MUJOCO_GL=osmesa for headless, or fix WSLg
    EGL error / rendering fails Missing EGL/Mesa libraries Run: sudo apt install -y libegl1-mesa-dev libgles2-mesa-dev
    Permission denied errors File permissions mismatch between Windows and WSL2 Work in ~/ not /mnt/c/; run chmod +x on scripts
    DLL load failed (native Windows) Missing Visual C++ Redistributable or wrong CUDA DLLs Install VC++ Redist; verify CUDA PATH order
    WSLg display not working WSL not updated or Wayland issue Run wsl --update in PowerShell; try export DISPLAY=:0
    CUDA out of memory Batch size too large or memory leak Reduce batch size, reduce num_envs, call torch.cuda.empty_cache()
    Python version conflicts System Python interfering with venv/conda Always activate your venv/conda env; use which python to verify
    ModuleNotFoundError: mujoco MuJoCo not installed in the active environment Activate your venv/conda, then pip install mujoco==3.1.3
    subprocess-exited-with-error during pip install Missing build dependencies Install build-essential cmake (WSL2) or Visual Studio Build Tools (Windows)

     

    Detailed Fix: MuJoCo Rendering in WSL2

    Rendering is the most frequent source of difficulty. A systematic approach to resolving it is presented below.

    # Step 1: Check if WSLg is running
    ls /tmp/.X11-unix/
    # Should list at least X0 or X1
    
    # Step 2: Check DISPLAY variable
    echo $DISPLAY
    # Should be something like :0 or :1
    
    # Step 3: Test with a simple OpenGL app
    sudo apt install -y mesa-utils
    glxinfo | head -20
    # Should show "direct rendering: Yes" for GPU acceleration
    
    # Step 4: If rendering still fails, try different backends
    export MUJOCO_GL=egl     # Hardware EGL (preferred)
    # or
    export MUJOCO_GL=osmesa  # Software rendering (slower but always works)
    # or
    export MUJOCO_GL=glfw    # GLFW (requires display)
    
    # Step 5: Test MuJoCo rendering
    python -c "
    import mujoco
    import numpy as np
    
    model = mujoco.MjModel.from_xml_string('')
    data = mujoco.MjData(model)
    
    renderer = mujoco.Renderer(model, height=480, width=640)
    mujoco.mj_step(model, data)
    renderer.update_scene(data)
    pixels = renderer.render()
    print(f'Rendered frame: {pixels.shape}')  # Should be (480, 640, 3)
    print('Rendering works!')
    "
    Caution: When switching between MUJOCO_GL backends, the Python session should be restarted completely. MuJoCo initialises the rendering backend on first import and caches it.

    Integration with VS Code

    VS Code is well suited to OpenClaw development, particularly when using WSL2. Microsoft’s WSL extension provides a native-Linux working experience while the editor itself runs on Windows.

    Setting Up VS Code with WSL2

    # Install the WSL extension in VS Code (from Windows)
    # 1. Open VS Code
    # 2. Go to Extensions (Ctrl+Shift+X)
    # 3. Search for "WSL" by Microsoft
    # 4. Click Install
    
    # Open your OpenClaw project from WSL2
    cd ~/robotics/openclaw
    code .

    This command opens VS Code on Windows but connects it to the WSL2 filesystem. The terminal inside VS Code uses the WSL2 bash shell, and all file operations occur on the Linux filesystem, combining the advantages of both environments.

    Setting Up Debugging

    Create a launch configuration at .vscode/launch.json in the project.

    {
        "version": "0.2.0",
        "configurations": [
            {
                "name": "Train GraspCube",
                "type": "debugpy",
                "request": "launch",
                "program": "${workspaceFolder}/train_grasp.py",
                "args": ["--env", "GraspCube-v1", "--total-timesteps", "10000"],
                "console": "integratedTerminal",
                "env": {
                    "CUDA_VISIBLE_DEVICES": "0",
                    "MUJOCO_GL": "egl"
                },
                "python": "${workspaceFolder}/venv/bin/python"
            },
            {
                "name": "Debug Current File",
                "type": "debugpy",
                "request": "launch",
                "program": "${file}",
                "console": "integratedTerminal",
                "python": "${workspaceFolder}/venv/bin/python"
            },
            {
                "name": "Evaluate Model",
                "type": "debugpy",
                "request": "launch",
                "program": "${workspaceFolder}/evaluate.py",
                "args": ["--model", "experiments/best_model/best_model.zip"],
                "console": "integratedTerminal",
                "python": "${workspaceFolder}/venv/bin/python"
            }
        ]
    }

    Recommended Extensions for Robotics Development

    • Python (Microsoft): Core Python support with IntelliSense, linting, and debugging
    • Pylance: Fast, feature-rich Python language server
    • WSL (Microsoft): Seamless WSL2 integration
    • Jupyter: For interactive experimentation and visualization
    • GitLens: Enhanced Git integration for tracking changes
    • YAML: Syntax highlighting for OpenClaw config files
    • Docker (Microsoft): If using the Docker installation method
    • Remote – SSH: For connecting to remote training servers
    • Error Lens: Inline error display—catches issues before running

    Workspace Settings

    Create .vscode/settings.json for project-specific configuration.

    {
        "python.defaultInterpreterPath": "${workspaceFolder}/venv/bin/python",
        "python.linting.enabled": true,
        "python.linting.flake8Enabled": true,
        "python.formatting.provider": "black",
        "python.formatting.blackArgs": ["--line-length", "100"],
        "editor.formatOnSave": true,
        "editor.rulers": [100],
        "files.exclude": {
            "**/__pycache__": true,
            "**/*.pyc": true,
            "**/experiments/*/checkpoints": true
        },
        "terminal.integrated.env.linux": {
            "MUJOCO_GL": "egl",
            "CUDA_VISIBLE_DEVICES": "0"
        }
    }

    Next Steps and Resources

    A fully functional OpenClaw installation on Windows 11 is now in place. The following directions may be explored next.

    Building Custom Environments

    OpenClaw’s environment API follows the Gymnasium standard, which makes the creation of custom tasks straightforward.

    import openclaw
    from openclaw.envs import BaseManipulationEnv
    
    class MyCustomTask(BaseManipulationEnv):
        """Custom manipulation task with your own reward function."""
    
        def __init__(self, **kwargs):
            super().__init__(
                model_path="path/to/your/model.xml",
                **kwargs
            )
    
        def _get_obs(self):
            # Define your observation space
            return {
                'robot_state': self._get_robot_state(),
                'object_state': self._get_object_state(),
                'goal': self._get_goal(),
            }
    
        def _compute_reward(self, achieved_goal, desired_goal, info):
            # Define your reward function
            distance = np.linalg.norm(achieved_goal - desired_goal)
            return -distance  # Dense reward: minimize distance
    
        def _check_success(self, achieved_goal, desired_goal):
            distance = np.linalg.norm(achieved_goal - desired_goal)
            return distance < 0.05  # 5cm threshold
    
    # Register the environment
    openclaw.register(
        id='MyCustomTask-v1',
        entry_point='my_envs:MyCustomTask',
        max_episode_steps=200,
    )

    Sim-to-Real Transfer Basics

    The ultimate goal of simulation training is the deployment of policies on real robots. Key techniques include the following.

    • Domain randomisation: vary physics parameters (friction, mass, damping) during training so that the policy generalises.
    • System identification: measure the real robot's parameters and match them in simulation.
    • Asymmetric actor-critic: grant the critic access to privileged simulation information while the actor uses only observations available in the real world.
    • Progressive transfer: begin with simple tasks and increase complexity incrementally.

    Contributing to OpenClaw

    Open-source robotics depends on community contributions. The following avenues for involvement are particularly useful.

    • Report bugs through GitHub Issues with detailed reproduction steps.
    • Contribute new environments for additional manipulation tasks.
    • Improve Windows compatibility, given that the experience of completing this setup is itself valuable.
    • Write documentation and tutorials.
    • Share trained models and benchmark results.

    Community and Learning Resources

    • OpenClaw GitHub: Source code, issues, and discussions
    • MuJoCo Documentation: mujoco.readthedocs.io—essential for understanding the physics engine
    • Stable Baselines3 Docs: stable-baselines3.readthedocs.io,RL algorithm reference
    • Gymnasium API: gymnasium.farama.org—environment interface standard
    • Robotic Manipulation Course (MIT 6.881): Excellent free lectures on manipulation theory
    • DeepMind Control Suite: Related environment suite for continuous control
    • Papers: Search for "dexterous manipulation reinforcement learning" on arXiv for the latest research

    Final Thoughts

    Setting up a robotics AI framework on Windows 11 once required either a dual-boot Linux partition or hours of work resolving incompatible dependencies. That period has ended. With WSL2 providing near-native Linux performance, Conda offering cross-platform package management, and Docker delivering reproducible containers, Windows 11 is now a first-class platform for robotics simulation research.

    This guide has covered three complete installation paths for OpenClaw. The WSL2 method offers the best balance of compatibility and performance and is recommended for most users. The native Conda approach is appropriate for simpler use cases in which WSL2 should be avoided entirely. Docker is the appropriate choice when reproducibility is paramount, particularly in team environments.

    The discussion has extended beyond basic installation to cover the complete workflow: running environments, training reinforcement learning policies with PPO, monitoring with TensorBoard, optimising GPU performance, and resolving the most common Windows-specific issues. VS Code has also been configured for a professional development experience.

    The field of robotic manipulation is advancing rapidly. Frameworks such as OpenClaw permit experimentation with recent algorithms without access to physical robots. A Windows 11 machine equipped with a reasonable NVIDIA GPU is sufficient to begin training policies that may eventually run on real robotic hands.

    The gap between simulation and reality continues to narrow each year. The path forward involves experimenting, accepting initial failures, and training agents that progress from clumsy attempts to reliable performance. The Windows 11 setup is now prepared, and only the work itself remains.

    Key Takeaway: Windows 11 with WSL2 provides a near-seamless experience for running Linux-native robotics frameworks. With the installation steps in this guide, the path from a fresh Windows machine to training robotic manipulation policies can be completed in under an hour.

    References

    1. MuJoCo Documentation—mujoco.readthedocs.io
    2. Stable Baselines3 Documentation—stable-baselines3.readthedocs.io
    3. Microsoft WSL2 Documentation,learn.microsoft.com/en-us/windows/wsl/
    4. NVIDIA CUDA on WSL—docs.nvidia.com/cuda/wsl-user-guide/
    5. NVIDIA Container Toolkit—docs.nvidia.com/datacenter/cloud-native/container-toolkit/
    6. Docker Desktop for Windows,docs.docker.com/desktop/install/windows-install/
    7. Gymnasium API Reference—gymnasium.farama.org
    8. Schulman, J., et al. "Proximal Policy Optimization Algorithms." arXiv:1707.06347 (2017)
    9. OpenAI. "Learning Dexterous In-Hand Manipulation." arXiv:1808.00177 (2018)
    10. Todorov, E., Erez, T., Tassa, Y. "MuJoCo: A physics engine for model-based control." IROS 2012
  • How to Create Professional PowerPoint Presentations Using Claude Cowork: A Step-by-Step Guide

    Summary

    What this post covers: A hands-on guide to building professional PowerPoint decks with Claude Cowork using three distinct workflows: direct computer use, programmatic generation with python-pptx, and AI-assisted outlining with manual polish.

    Key insights:

    • Knowledge workers spend roughly eight hours per week on slides, and Claude Cowork can cut that effort by about 90 percent by combining agentic computer control with code generation.
    • Direct computer use is fastest for one-off internal decks, python-pptx is the right choice for recurring or data-driven reports, and the outline-and-edit method preserves the most creative control for high-stakes presentations.
    • Among AI presentation tools (Copilot, Gamma, Beautiful.ai, SlidesGPT), Cowork stands out because it is a general-purpose agent that can also research, analyze data, and automate work end-to-end, not just generate slides.
    • Better prompts (audience, structure, constraints, examples) consistently produce better decks; an iterative four-pass workflow (skeleton, narrative, design, speaker notes) beats one-shot generation.
    • Cowork has real limitations around fine pixel-level design, large images, and complex animations, so a human review pass before presenting is still required.

    Main topics: Introduction, Prerequisites and Setup, Method 1: Direct Computer Use with Cowork, Method 2: Python-pptx Script Generation, Method 3: Outline and Manual Creation, Practical Examples, Advanced Techniques, Prompt Engineering for Better Presentations, Comparison: Claude Cowork vs Other AI Presentation Tools, Limitations and Workarounds, Best Practices for AI-Generated Presentations, Final Thoughts, References.

    Introduction: The Presentation Problem

    A statistic worth noting: the average professional spends eight hours per week creating presentations. An entire workday each week is consumed by adjusting text boxes, selecting chart styles, aligning bullet points, and reconsidering whether a title slide looks sufficiently formal. Over the course of a year, the total exceeds 400 hours, equivalent to roughly ten work weeks.

    That time can be reduced by approximately 90 percent. The mechanism is neither a template gallery nor an outsourced designer. It is an AI agent capable of observing the screen, opening PowerPoint, building slides in real time, and generating entire presentation files programmatically through Python code, all from a single natural-language prompt.

    Claude Cowork provides precisely this capability. Released by Anthropic as part of its Claude desktop application, Cowork is an agentic computer-use feature that converts Claude from a chatbot into a fully featured desktop assistant. It can control the mouse and keyboard, execute scripts, browse the web for research, and operate autonomously on multi-step tasks.

    This guide examines three distinct methods for creating professional PowerPoint presentations using Claude Cowork: fully hands-off computer use, programmatic generation with the python-pptx library, and structured outlines refined manually. Four real-world presentation decks are built step by step, advanced techniques such as data-driven automation are explored, and Cowork is compared with every major AI presentation tool currently available.

    Whether the reader is a startup founder rehearsing a pitch, a consultant assembling a quarterly business review, or an engineer explaining system architecture to stakeholders, this guide will alter the process of presentation creation substantially.

    The guide proceeds as follows.

    Claude Cowork Presentation Workflow Brief / Topic Your idea or prompt Claude Generates Outline & Content Slide Design Build & format deck Review & Refine Check & adjust Final.pptx Ready to present Step 1 Step 2 Step 3 Step 4 Step 5

    Prerequisites and Setup

    Before the methods are examined, a few prerequisites must be in place. Setup typically takes approximately five minutes.

    What Is Required

    Requirement Details
    Claude Subscription Claude Pro ($20/mo), Max ($100/mo or $200/mo), or Team plan. Cowork is not available on the free tier.
    Claude Desktop App Download from claude.ai/download—available for macOS and Windows.
    Cowork Enabled Go to Claude Desktop → Settings → Feature Previews → Enable “Computer Use” / Cowork.
    Presentation Software Microsoft PowerPoint (desktop), Google Slides (browser), or LibreOffice Impress.
    Python (for Method 2) Python 3.9+ with pip install python-pptx. Optional but powerful.

     

    Enabling Cowork in Claude Desktop

    If Cowork has not yet been enabled, the configuration proceeds as follows:

    1. Open the Claude desktop app (not the browser version; Cowork requires the native application).
    2. Click the profile icon in the bottom-left corner.
    3. Navigate to Settings → Feature Previews.
    4. Toggle on “Computer Use” (also labelled “Cowork” in newer versions).
    5. Grant the required permissions: Claude requires screen access and input control.
    6. Restart the application if prompted.

    Once enabled, a new option to start a “Cowork” session appears in the Claude chat interface. The option instructs Claude that it may observe the screen and interact with desktop applications.

    Caution: Cowork’s computer use is currently in research preview. Claude requests confirmation before taking actions, and continued supervision is recommended, particularly during clicking, typing, or file-saving operations. The system should be regarded as a capable assistant whose actions still warrant oversight.

    Method 1: Direct Computer Use with Cowork

    This is the most striking method and the one that most closely resembles autonomous operation. The user specifies the desired presentation, and Claude opens PowerPoint, creates slides, enters content, applies formatting, and saves the file while the user observes.

    How Computer Use Works

    When a Cowork session begins, Claude obtains the following capabilities:

    • Screen observation. Periodic screenshots allow Claude to interpret what is displayed.
    • Mouse control. Claude can click buttons, menus, and interface elements.
    • Keyboard input. Claude can enter text, use keyboard shortcuts, and navigate applications.
    • Terminal command execution. Claude can launch applications, run scripts, and manage files.

    The result is that Claude can interact with PowerPoint (or Google Slides, or any other presentation tool) in much the same way as a human user, although more rapidly and without creative blocks.

    Step-by-Step Walkthrough

    Step 1: Start a Cowork session. In the Claude desktop app, open a new conversation and select the Cowork mode. A banner confirms that Claude may now interact with the computer.

    Step 2: Provide a presentation brief. An example prompt follows:

    I need you to create a 10-slide PowerPoint presentation for a quarterly business review.
    
    Company: Acme Corp
    Quarter: Q1 2026
    Key metrics:
    - Revenue: $4.2M (up 18% YoY)
    - New customers: 340
    - Churn rate: 2.1% (down from 3.4%)
    - NPS score: 72
    
    Sections needed:
    - Title slide with company logo placeholder
    - Executive summary
    - Revenue breakdown by product line
    - Customer acquisition funnel
    - Churn analysis
    - NPS trends
    - Key wins this quarter
    - Challenges and risks
    - Q2 priorities
    - Thank you / Q&A slide
    
    Style: Professional, dark blue theme, clean and minimal.
    Please open PowerPoint and create this deck for me.

    Step 3: Observe Claude’s work. After the action is confirmed, Claude will:

    1. Open PowerPoint from the taskbar or applications folder.
    2. Select a blank presentation (or apply a built-in theme if one was specified).
    3. Create the title slide and enter the title, subtitle, and date.
    4. Add new slides one by one, selecting appropriate layouts (title with content, two-column, or blank for charts).
    5. Enter all text content, including headings, bullet points, and data figures.
    6. Apply formatting such as font sizes, colours, and alignment.
    7. Apply a cohesive theme, adjusting the slide master where necessary.
    8. Save the file to the preferred location.

    Step 4: Review and refine. Once Claude completes the task, the user is notified that the deck is ready. The file should be opened, each slide reviewed, and adjustments requested as required:

    The revenue slide looks great, but can you:
    1. Make the revenue number larger and bold
    2. Add a simple bar chart placeholder showing Q1 vs Q4 comparison
    3. Change the background of the title slide to a gradient from dark blue to navy
    Tip: Formatting requests should be precise. Instead of “make it look better,” specify “increase the heading font to 28pt, use Calibri Bold, and left-align all bullet points with 1.5 line spacing.” The more precise the instruction, the better the output produced by Claude.

    Effective Prompts for Computer Use

    Presentation quality depends substantially on prompt quality. The following prompt patterns work well with Cowork’s computer use:

    For a pitch deck:

    Open PowerPoint and create a 12-slide startup pitch deck for a B2B SaaS company
    called "DataFlow" that provides real-time analytics for e-commerce.
    
    Funding stage: Series A, seeking $5M
    Traction: $1.2M ARR, 85 customers, 140% net revenue retention
    
    Use a modern, clean design with a primary color of #1a73e8 (Google blue).
    Include placeholder boxes where charts and screenshots should go.
    Add speaker notes to every slide with talking points.

    For a training presentation:

    Create a 15-slide onboarding training deck for new software engineers.
    
    Topics to cover:
    - Company tech stack overview
    - Development workflow (Git, CI/CD, code review)
    - Architecture overview (microservices, AWS infrastructure)
    - Security best practices
    - First-week checklist
    
    Style: Light theme, friendly and approachable. Use icons or emoji where appropriate.
    Include a quiz slide at the end with 5 multiple-choice questions.

    Method 2: Python-pptx Script Generation

    When pixel-perfect control, repeatable automation, or presentations driven by live data are required, the python-pptx method is the most appropriate option. Instead of manipulating PowerPoint visually, Claude is asked to generate a Python script that creates the .pptx file programmatically.

    This approach is particularly powerful because:

    • Presentation scripts can be version-controlled in Git.
    • Data can be ingested from CSV, Excel, databases, or APIs.
    • Updated presentations can be regenerated with a single command.
    • Absolute precision over positioning, sizing, and styling is preserved.

    Getting Started with python-pptx

    The library is installed as follows:

    pip install python-pptx

    Claude can then be requested—either in a regular chat or in a Cowork session—to generate complete scripts. The principal building blocks are described below.

    Creating a Title Slide

    from pptx import Presentation
    from pptx.util import Inches, Pt, Emu
    from pptx.dml.color import RGBColor
    from pptx.enum.text import PP_ALIGN
    
    prs = Presentation()
    prs.slide_width = Inches(13.333)  # Widescreen 16:9
    prs.slide_height = Inches(7.5)
    
    # Title slide
    slide_layout = prs.slide_layouts[6]  # Blank layout for full control
    slide = prs.slides.add_slide(slide_layout)
    
    # Background color
    background = slide.background
    fill = background.fill
    fill.solid()
    fill.fore_color.rgb = RGBColor(0x1a, 0x1a, 0x2e)  # Dark navy
    
    # Title text
    from pptx.util import Inches, Pt
    txBox = slide.shapes.add_textbox(Inches(1), Inches(2), Inches(11), Inches(2))
    tf = txBox.text_frame
    tf.word_wrap = True
    p = tf.paragraphs[0]
    p.text = "Q1 2026 Business Review"
    p.font.size = Pt(44)
    p.font.bold = True
    p.font.color.rgb = RGBColor(0xFF, 0xFF, 0xFF)
    p.alignment = PP_ALIGN.LEFT
    
    # Subtitle
    p2 = tf.add_paragraph()
    p2.text = "Acme Corp — Confidential"
    p2.font.size = Pt(20)
    p2.font.color.rgb = RGBColor(0xBB, 0xBB, 0xBB)
    p2.alignment = PP_ALIGN.LEFT
    
    prs.save("q1_review.pptx")
    print("Presentation saved!")

    Building Bullet Point Slides

    def add_content_slide(prs, title, bullets, bg_color=RGBColor(0xFF, 0xFF, 0xFF)):
        slide = prs.slides.add_slide(prs.slide_layouts[6])
    
        # Background
        background = slide.background
        fill = background.fill
        fill.solid()
        fill.fore_color.rgb = bg_color
    
        # Slide title
        title_box = slide.shapes.add_textbox(Inches(0.8), Inches(0.5), Inches(11), Inches(1))
        tf = title_box.text_frame
        p = tf.paragraphs[0]
        p.text = title
        p.font.size = Pt(32)
        p.font.bold = True
        p.font.color.rgb = RGBColor(0x1a, 0x1a, 0x2e)
    
        # Accent line under title
        from pptx.shapes import autoshape
        line = slide.shapes.add_shape(
            1,  # Rectangle
            Inches(0.8), Inches(1.45), Inches(2), Inches(0.05)
        )
        line.fill.solid()
        line.fill.fore_color.rgb = RGBColor(0x1a, 0x73, 0xe8)
        line.line.fill.background()
    
        # Bullet points
        content_box = slide.shapes.add_textbox(Inches(0.8), Inches(1.8), Inches(11), Inches(5))
        tf = content_box.text_frame
        tf.word_wrap = True
    
        for i, bullet in enumerate(bullets):
            if i == 0:
                p = tf.paragraphs[0]
            else:
                p = tf.add_paragraph()
            p.text = f"  {bullet}"
            p.font.size = Pt(20)
            p.font.color.rgb = RGBColor(0x33, 0x33, 0x33)
            p.space_after = Pt(12)
    
        return slide
    
    # Usage
    add_content_slide(prs, "Key Wins This Quarter", [
        "Landed 3 enterprise accounts worth $1.2M combined ARR",
        "Reduced customer onboarding time from 14 days to 3 days",
        "Launched self-serve analytics dashboard — 89% adoption in week one",
        "Engineering velocity up 34% after platform migration",
        "NPS improved from 64 to 72 — highest score in company history"
    ])

    Adding Charts

    from pptx.chart.data import CategoryChartData
    from pptx.enum.chart import XL_CHART_TYPE
    
    def add_chart_slide(prs, title, categories, series_data):
        slide = prs.slides.add_slide(prs.slide_layouts[6])
    
        # Title
        title_box = slide.shapes.add_textbox(Inches(0.8), Inches(0.5), Inches(11), Inches(1))
        tf = title_box.text_frame
        p = tf.paragraphs[0]
        p.text = title
        p.font.size = Pt(32)
        p.font.bold = True
    
        # Chart data
        chart_data = CategoryChartData()
        chart_data.categories = categories
    
        for series_name, values in series_data.items():
            chart_data.add_series(series_name, values)
    
        # Add chart to slide
        chart = slide.shapes.add_chart(
            XL_CHART_TYPE.COLUMN_CLUSTERED,
            Inches(1), Inches(1.8), Inches(11), Inches(5),
            chart_data
        ).chart
    
        # Style the chart
        chart.has_legend = True
        chart.legend.include_in_layout = False
        chart.style = 2
    
        return slide
    
    # Usage — Revenue by quarter
    add_chart_slide(prs, "Revenue Trend",
        ["Q2 2025", "Q3 2025", "Q4 2025", "Q1 2026"],
        {
            "Revenue ($M)": [2.8, 3.1, 3.6, 4.2],
            "Target ($M)": [3.0, 3.2, 3.5, 4.0]
        }
    )

    Adding Tables

    def add_table_slide(prs, title, headers, rows):
        slide = prs.slides.add_slide(prs.slide_layouts[6])
    
        # Title
        title_box = slide.shapes.add_textbox(Inches(0.8), Inches(0.5), Inches(11), Inches(1))
        tf = title_box.text_frame
        p = tf.paragraphs[0]
        p.text = title
        p.font.size = Pt(32)
        p.font.bold = True
    
        # Create table
        num_rows = len(rows) + 1  # +1 for header
        num_cols = len(headers)
        table_shape = slide.shapes.add_table(
            num_rows, num_cols,
            Inches(0.8), Inches(1.8), Inches(11.5), Inches(4.5)
        )
        table = table_shape.table
    
        # Header row
        for i, header in enumerate(headers):
            cell = table.cell(0, i)
            cell.text = header
            for paragraph in cell.text_frame.paragraphs:
                paragraph.font.bold = True
                paragraph.font.size = Pt(14)
                paragraph.font.color.rgb = RGBColor(0xFF, 0xFF, 0xFF)
            cell.fill.solid()
            cell.fill.fore_color.rgb = RGBColor(0x1a, 0x1a, 0x2e)
    
        # Data rows
        for row_idx, row_data in enumerate(rows):
            for col_idx, value in enumerate(row_data):
                cell = table.cell(row_idx + 1, col_idx)
                cell.text = str(value)
                for paragraph in cell.text_frame.paragraphs:
                    paragraph.font.size = Pt(12)
                if row_idx % 2 == 0:
                    cell.fill.solid()
                    cell.fill.fore_color.rgb = RGBColor(0xF0, 0xF0, 0xF0)
    
        return slide
    
    # Usage
    add_table_slide(prs, "Product Line Performance",
        ["Product", "Revenue", "Growth", "Margin"],
        [
            ["Analytics Pro", "$1.8M", "+24%", "78%"],
            ["DataSync", "$1.4M", "+15%", "72%"],
            ["API Gateway", "$0.7M", "+31%", "85%"],
            ["Consulting", "$0.3M", "-5%", "45%"],
        ]
    )

    Running the Generated Script

    Once Claude has produced the complete script, two execution options are available:

    Option A: Cowork executes the script.

    Please run the Python script you just created and open the resulting
    PowerPoint file so I can review it.

    Cowork opens a terminal, executes the script, and then opens the generated .pptx file in PowerPoint.

    Option B: The user executes the script directly.

    python create_presentation.py
    Key Takeaway: The python-pptx method provides a reusable, version-controlled, and data-driven approach to presentation generation. Scripts can be saved, parameterised, and rerun to regenerate updated decks whenever new data arrives. The approach is particularly valuable for recurring presentations such as weekly reports or monthly board updates.

    Method 3: Outline and Manual Creation

    Full automation is not always desirable. In some cases, Claude’s strategic contribution—structure, narrative arc, and content—is valuable, but the user prefers to design the slides personally. Method 3 is intended for those who value creative control while wishing to avoid the blank-page problem.

    How It Works

    Claude is asked to produce a detailed slide-by-slide outline that includes:

    • Slide title and layout recommendation
    • Exact content (bullet points, key figures, quotes)
    • Speaker notes with talking points and timing
    • Design suggestions (colors, imagery, chart types)
    • Transition recommendations between slides

    Example Prompt

    I need to create a presentation about our company's cloud migration strategy.
    
    Audience: C-suite executives (non-technical)
    Duration: 20 minutes
    Slides: 12-15
    
    Please create a detailed slide-by-slide outline with:
    1. Slide title
    2. Layout type (title slide, content, two-column, full-image, chart, etc.)
    3. Exact text content for each element
    4. Speaker notes (what I should say, not what's on screen)
    5. Design notes (suggested imagery, colors, chart types)
    6. Estimated time per slide
    
    Focus on business impact, cost savings, and risk mitigation.
    Avoid technical jargon — this is for executives, not engineers.

    What Claude Produces

    Claude generates output of the following form for each slide:

    SLIDE 4: The Cost of Staying Put
    Layout: Two-column with key metric callout
    
    LEFT COLUMN:
    - Current infrastructure costs: $2.4M/year
    - Annual growth in server costs: 23%
    - Unplanned downtime last year: 47 hours
    - Revenue impact of downtime: $890K
    
    RIGHT COLUMN:
    [Suggested chart: Line graph showing infrastructure cost trajectory
    over 5 years if no action is taken — hockey stick curve]
    
    KEY METRIC (large, centered below columns):
    "By 2028, maintaining current infrastructure will cost $6.1M/year"
    
    SPEAKER NOTES:
    "This slide is your wake-up call moment. Pause after revealing the
    $6.1M figure. Let it sink in. Then say: 'And that's just the
    direct cost — it doesn't include the opportunity cost of our
    engineering team spending 30% of their time on maintenance instead
    of building new features.' Estimated time: 2 minutes."
    
    DESIGN NOTES:
    Use red/warning colors for the cost figures. The chart should show
    a clear upward trend that looks unsustainable. Consider a subtle
    red gradient background to reinforce urgency.

    The level of detail allows each slide to be built quickly because the strategic work has already been completed. Only the design execution remains.

    Recommended Slide Structure for Professional Presentations TITLE Subtitle / Date Title Slide Hook the audience • Section 1 • Section 2 • Section 3 Agenda Set expectations Content Content Content Content Slides 3–5 focused sections Key point 1 Key point 2 Key point 3 Summary Reinforce key ideas Q&A Q&A / Next Steps Close with action

    Tip: Claude should also be requested to generate a “presentation narrative arc,” a one-paragraph summary of the emotional progression intended for the audience. For example: “Begin with urgency around the cost problem, move to hope through the cloud opportunity, build confidence with the migration plan, and close with optimism about the future state.” Such an arc keeps the deck cohesive.

    Practical Examples: Four Real-World Decks

    Concrete examples are more useful than abstract discussion. The four presentations below illustrate common scenarios, with the exact prompts to provide to Cowork and the expected outputs.

    Quarterly Business Review (10 Slides)

    The prompt:

    Create a 10-slide quarterly business review deck in PowerPoint.
    
    Company: TechFlow Inc.
    Period: Q1 2026
    
    Data:
    - Revenue: $8.7M (plan was $8.2M) — 106% attainment
    - Gross margin: 74% (up from 71%)
    - Headcount: 142 (added 18 in Q1)
    - Customer count: 520 (net new: 47)
    - Logo churn: 3 customers (0.6%)
    - NRR: 118%
    - Top deal: Megacorp ($420K ACV)
    - Pipeline for Q2: $12.4M weighted
    
    Slides needed:
    1. Title slide
    2. Executive summary — 4 key metrics in large numbers
    3. Revenue vs plan (bar chart)
    4. Revenue by segment (pie chart: Enterprise 55%, Mid-market 30%, SMB 15%)
    5. Customer metrics (new logos, churn, NRR)
    6. Top wins — 3 biggest deals with logos
    7. Product updates — 3 major releases
    8. Team growth — hiring progress
    9. Q2 outlook and priorities
    10. Appendix — detailed financial table
    
    Use a clean, modern theme with navy (#1a1a2e) and electric blue (#1a73e8).
    Save as "TechFlow_Q1_2026_QBR.pptx"

    What Cowork produces: A complete 10-slide deck with formatted charts, styled tables, consistent branding, and speaker notes. The entire process takes approximately three to five minutes for computer use, or it is generated almost instantly as a python-pptx script.

    Startup Pitch Deck (12 Slides)

    The prompt:

    Create a 12-slide Series A pitch deck for an AI-powered legal tech startup.
    
    Company: LegalMind AI
    Mission: Making legal research 10x faster with AI
    Stage: Series A — raising $8M
    Key metrics: $2.1M ARR, 200+ law firms, 95% retention, 3x YoY growth
    
    Follow the classic pitch deck structure:
    1. Title / hook
    2. Problem — legal research takes 10+ hours per case
    3. Solution — AI-powered case law analysis
    4. Product demo screenshots (use placeholder images)
    5. Market size — $28B legal tech market, $4B serviceable
    6. Business model — SaaS, $500-$5,000/month per firm
    7. Traction — growth chart, key logos, metrics
    8. Competition — 2x2 quadrant (speed vs accuracy)
    9. Team — 3 founders with relevant backgrounds
    10. Go-to-market strategy
    11. Financial projections — 3-year revenue forecast
    12. The ask — $8M for engineering, sales, expansion
    
    Design: Minimalist, white background, accent color #6C5CE7 (purple).
    Make it investor-ready — clean, no clutter, big numbers.

    Technical Architecture Presentation

    The prompt:

    Create a technical architecture presentation for our platform migration.
    
    Audience: Engineering team (technical)
    Length: 15 slides
    
    Cover:
    - Current architecture (monolith on EC2)
    - Target architecture (microservices on EKS)
    - Migration phases (4 phases over 6 months)
    - Service decomposition plan
    - Data migration strategy
    - CI/CD pipeline changes
    - Monitoring and observability stack
    - Risk mitigation
    - Timeline and milestones
    
    Include architecture diagram descriptions (text-based, I'll replace
    with actual diagrams) and code snippets showing key config changes.
    
    Style: Dark theme suitable for screen sharing. Use monospace fonts
    for technical content.

    Sales Proposal Deck

    The prompt:

    Create a sales proposal deck for a prospective enterprise customer.
    
    Our company: CloudSync (data integration platform)
    Prospect: Global Retail Corp (Fortune 500 retailer)
    Deal size: $350K/year
    Competition: They're also evaluating Informatica and Fivetran
    
    Create 10 slides:
    1. Title with both company logos (placeholders)
    2. Understanding their challenges (data silos, slow reporting)
    3. Our solution overview
    4. Technical fit — integration with their stack (Snowflake, SAP, Shopify)
    5. Implementation timeline (8 weeks)
    6. Case study — similar retailer, 60% faster reporting
    7. ROI analysis — $1.2M annual savings
    8. Pricing — 3 tiers with recommended option highlighted
    9. Why us vs competition (comparison table)
    10. Next steps and timeline
    
    Design: Professional, trustworthy. Use their brand colors (green #2E7D32)
    alongside ours (blue #1565C0).
    Key Takeaway: Each prompt above includes specific data, a clear structure, design preferences, and context about the audience. The more detail provided at the outset, the less iteration is required. A well-crafted prompt saves more time than any tool feature.

    Advanced Techniques

    Once the basics are familiar, the following advanced approaches can extend the presentation workflow further.

    Automated Report Decks with Scheduled Tasks

    Cowork supports scheduled tasks, sometimes called “recurring tasks.” Claude can therefore be configured to generate presentations on a schedule. For example, every Monday morning a fresh weekly metrics deck can be deposited in the Downloads folder, populated with the latest data.

    Configuration proceeds as follows:

    Set up a recurring task: Every Monday at 8 AM, generate a weekly
    metrics presentation.
    
    Steps:
    1. Read the latest data from our metrics spreadsheet at
       ~/Documents/weekly_metrics.csv
    2. Run the Python script at ~/scripts/generate_weekly_deck.py
       with the CSV as input
    3. Save the output as ~/Presentations/Weekly_Report_[DATE].pptx
    4. Notify me when complete

    Cowork retains the task and executes it on schedule: the latest data is read, the generation script is run, and an updated deck is produced each week without manual intervention.

    Data-Driven Presentations from CSV and Excel

    One of the most powerful patterns is to provide Cowork with a data file and allow it to build a presentation around the data:

    I've attached our Q1 sales data in sales_q1_2026.csv. Please:
    
    1. Analyze the data and identify key trends
    2. Create a 10-slide presentation that tells the story of our Q1 sales
    3. Include charts generated from the actual data
    4. Highlight the top 5 performing products and bottom 3
    5. Add a forecast slide projecting Q2 based on current trends
    6. Use the python-pptx approach to ensure charts are data-accurate
    
    The audience is our VP of Sales — focus on actionable insights,
    not just data display.

    Cowork reads the CSV, performs the analysis, generates appropriate visualisations, and builds a presentation that tells a coherent story from the data.

    Using Projects for Brand Consistency

    Claude’s Projects feature allows context to be saved across conversations. The feature can be used to maintain brand guidelines:

    Add this to our project context:
    
    BRAND GUIDELINES FOR ALL PRESENTATIONS:
    - Primary color: #1a1a2e (Dark Navy)
    - Secondary color: #1a73e8 (Electric Blue)
    - Accent color: #e8f4fd (Light Blue)
    - Font: Calibri for body, Calibri Light for headings
    - Logo: Always place in top-right corner of title slide
    - Footer: "Confidential — [Company Name] — [Date]" on every slide
    - Slide numbers: Bottom-right, starting from slide 2
    - Chart style: Minimal grid lines, data labels on bars
    - Maximum 6 bullet points per slide, maximum 8 words per bullet

    Every presentation that Claude is asked to create within that Project then follows these guidelines automatically.

    From Research to Deck: Web Search Integration

    Cowork can browse the web. It can therefore research a topic and build a presentation from the resulting findings:

    I need a presentation on "The State of AI in Healthcare — 2026" for
    a healthcare conference.
    
    Please:
    1. Research the latest trends, statistics, and key players in AI healthcare
    2. Find 3-4 compelling case studies of AI improving patient outcomes
    3. Get market size data and growth projections
    4. Compile everything into a 15-slide presentation
    5. Include source citations on each slide
    6. Add a references slide at the end
    
    Target audience: Hospital administrators (non-technical).
    Focus on ROI and patient outcomes, not technical architecture.

    Cowork opens a browser, searches for relevant information, compiles findings, and builds a fully sourced presentation in a single workflow.

    Prompt Engineering for Better Presentations

    The quality of an AI-generated presentation is directly proportional to the quality of the prompt. The templates below consistently produce strong results.

    Effective Prompt Templates

    Presentation Type Key Prompt Elements Example Snippet
    Pitch Deck Problem, solution, market size, traction, team, ask “Create a 12-slide Series A pitch… $2M ARR, raising $8M…”
    Business Review KPIs, period comparison, wins, challenges, outlook “10-slide QBR… revenue $4.2M (+18% YoY)… Q2 priorities…”
    Technical Architecture Current state, target state, migration plan, risks “Architecture deck for engineering… monolith to microservices…”
    Sales Proposal Customer pain, solution fit, ROI, pricing, vs. competition “Proposal for Fortune 500 retailer… competing against Informatica…”
    Training / Onboarding Learning objectives, step-by-step content, quizzes “15-slide onboarding deck for new engineers… include quiz…”
    Conference Talk Narrative arc, audience level, demo placeholders, Q&A “30-minute keynote on AI trends… for non-technical CxOs…”
    Board Update Financial summary, strategic progress, risks, asks “Board deck… focus on runway, burn rate, strategic milestones…”

     

    Tips for Writing Effective Prompts

    Always specify the audience. A presentation for engineers differs substantially from one for investors. Telling Claude who will be in the room shapes vocabulary, level of detail, and persuasion strategy.

    State the number of slides. Without an explicit target, Claude may produce eight slides or thirty. Specify clearly, for example “Create exactly 12 slides.”

    Define the tone. “Professional but approachable” yields different results from “formal and data-heavy” or “energetic and startup-oriented.” A few adjectives provide useful direction.

    Include real data. The principal difference between a generic AI deck and a useful one is the presence of real numbers. Supplying actual metrics renders the resulting presentation immediately actionable.

    Request speaker notes. Even when the material is familiar, talking points reduce preparation time. A useful request is “detailed speaker notes with timing estimates for each slide.”

    Specify design constraints. Brand colours, preferred fonts, layout preferences (minimal compared with data-dense), and a light or dark theme should be stated.

    Indicate what to exclude. Constraints such as “No clip art. No stock photo clichés. No slides with more than 20 words.” often improve output quality more effectively than additive instructions.

    Comparison: Claude Cowork and Other AI Presentation Tools

    Claude Cowork is not the only AI tool that supports presentation creation. Its position relative to alternative tools is summarised below.

    Feature Claude Cowork Microsoft Copilot Gamma.app Beautiful.ai SlidesGPT
    Creates.pptx files Yes (both methods) Yes (native) Export only Export only Yes
    Works with existing PPT Yes (computer use) Yes (native) No No No
    Data-driven charts Yes (python-pptx) Yes (Excel integration) Limited Limited Basic
    Programmatic/scriptable Yes (Python scripts) No API only No API only
    Web research built in Yes Yes (Bing) Yes No No
    Scheduled automation Yes (Cowork tasks) No No No No
    Design quality (out of box) Good (needs guidance) Good (uses PPT themes) Excellent Excellent Average
    General AI assistant Yes (full Claude) Limited to Office Presentations only Presentations only Presentations only
    Price $20/mo (Pro) $30/mo (M365 Copilot) $10/mo (Plus) $12/mo (Pro) $4.17/deck

     

    When to choose Claude Cowork: Cowork is appropriate when maximum flexibility is required, that is, when a single tool must create presentations and also write code, analyse data, conduct research, and automate recurring workflows. It is the strongest option when presentation needs extend beyond well-designed slides into data analysis, scripting, and multi-step automation.

    Before vs After: AI-Assisted Presentation Creation Manual (Without AI) Research & structure 2.5 h Write slide content 2 h Design & formatting 2.5 h Review & polish 1.5 h Total: ~8.5 hours AI-Assisted (Claude Cowork) Write prompt & brief 5 min Claude generates deck 10 min Review & minor edits 7 min Final polish 3 min Total: ~25 minutes (95% faster) VS

    When to choose Copilot: Copilot is appropriate for users already embedded in the Microsoft ecosystem who want seamless integration with Excel, Word, and Teams. It operates natively inside PowerPoint, which provides better theme support and fewer formatting irregularities.

    When to choose Gamma or Beautiful.ai: These tools are appropriate when design quality is the principal concern and PowerPoint compatibility is not required. They produce visually striking decks with minimal effort, although the user is bound to their respective ecosystems.

    Limitations and Workarounds

    No tool is without weaknesses. A candid assessment of where Cowork’s presentation capabilities encounter limits, together with corresponding workarounds, is provided below.

    Computer Use Precision

    The limitation: Cowork’s computer use is in research preview. It interprets the screen via screenshots and therefore occasionally misclicks, selects the wrong menu item, or places text in the wrong text box. Complex PowerPoint interfaces with many nested menus can lead to confusion.

    The workaround: Use the python-pptx method for presentations that require pixel-perfect precision. Computer use should be reserved for simpler decks or for editing existing presentations where Claude can be guided step by step. Specific slides can also be zoomed into so that Claude can focus on one element at a time.

    Complex Animations and Transitions

    The limitation: Although Cowork can apply basic transitions such as fade and slide, complex animation sequences—such as bullet points appearing one by one with specific timing or morphing between slides—are difficult to achieve through computer use and are not fully supported in python-pptx.

    The workaround: Claude should build the content and static design, with animations added manually afterwards. Animating a finished deck requires substantially less time than building one from scratch. Alternatively, Claude can be asked to document the animation plan, for example: “Slide 5: bullets should appear on click, one at a time, with a 0.3s fade-in.”

    Image-Heavy Presentations

    The limitation: Claude cannot generate images, since it is a language model rather than an image generator. Cowork can search the web for images and insert them, but the results may not match the user’s brand aesthetic, and copyright considerations apply.

    The workaround: Claude should be asked to create placeholder boxes with descriptive labels such as “[Photo: Team celebrating product launch]” or “[Chart: Market size growth 2020–2026].” The user or a designer can then replace these with actual assets. For icons, Claude can suggest free icon libraries such as Google Material Icons or Feather Icons.

    Custom Template Compliance

    The limitation: If the user’s organisation requires a strict PowerPoint template with custom slide masters, layouts, and placeholders, Cowork may not navigate the template perfectly through computer use.

    The workaround: python-pptx should be used with the organisation’s template file as the base:

    from pptx import Presentation
    
    # Load your company template
    prs = Presentation('company_template.pptx')
    
    # Now add slides using the template's layouts
    slide_layout = prs.slide_layouts[1]  # Your company's content layout
    slide = prs.slides.add_slide(slide_layout)
    
    # Content goes into the template's predefined placeholders
    title = slide.placeholders[0]
    title.text = "Q1 Revenue Analysis"
    
    body = slide.placeholders[1]
    body.text = "Revenue grew 18% year-over-year..."
    
    prs.save('branded_presentation.pptx')

    The approach ensures that every slide uses approved layouts, fonts, and branding elements.

    Very Large Presentations

    The limitation: For decks exceeding 30–40 slides, computer use can become slow and may lose context regarding earlier slides. python-pptx scripts can also become unwieldy at scale.

    The workaround: Large presentations should be broken into sections. Claude can be asked to create slides 1–15, the result reviewed, and slides 16–30 added subsequently. For python-pptx, modular functions (one function per section) keep the code maintainable.

    Caution: AI-generated presentations should always be reviewed before they are shared externally. Data accuracy, spelling of names and company-specific terms, and the fidelity of charts to the underlying data must be verified. AI systems can fabricate numbers or subtly misrepresent trends when the source data is ambiguous.

    Best Practices for AI-Generated Presentations

    The following practices consistently produce the strongest results in extensive use of Claude Cowork.

    Always Review and Refine

    AI-generated slides should be treated as a first draft, not a final product. Claude advances the user 80–90% of the way to completion in a fraction of the usual time. The final 10–20%—personal touches, precise data verification, and nuances known only to the author—is what makes a presentation truly excellent.

    A review checklist should be built:

    • Are all numbers accurate and up to date?
    • Do charts correctly represent the data?
    • Are company names, product names, and people’s names spelled correctly?
    • Does the narrative flow logically from slide to slide?
    • Is the tone appropriate for the audience?
    • Are there any claims that need citations?

    Maintain Brand Consistency

    Claude’s Projects feature should be used to store brand guidelines including colours, fonts, logo placement, and slide layouts. This eliminates the need to repeat brand instructions in every prompt and ensures consistency across all presentations.

    A more robust approach is to create a python-pptx base module containing the brand settings:

    # brand.py — import this in all presentation scripts
    from pptx.dml.color import RGBColor
    from pptx.util import Pt
    
    # Company colors
    PRIMARY = RGBColor(0x1a, 0x1a, 0x2e)
    SECONDARY = RGBColor(0x1a, 0x73, 0xe8)
    ACCENT = RGBColor(0xe8, 0xf4, 0xfd)
    TEXT_DARK = RGBColor(0x33, 0x33, 0x33)
    TEXT_LIGHT = RGBColor(0xFF, 0xFF, 0xFF)
    SUCCESS = RGBColor(0x27, 0xAE, 0x60)
    WARNING = RGBColor(0xE7, 0x4C, 0x3C)
    
    # Typography
    HEADING_SIZE = Pt(32)
    SUBHEADING_SIZE = Pt(24)
    BODY_SIZE = Pt(18)
    CAPTION_SIZE = Pt(12)
    
    # Standard settings
    FONT_FAMILY = "Calibri"
    MAX_BULLETS_PER_SLIDE = 6
    MAX_WORDS_PER_BULLET = 8

    Keep Slides Minimal

    The most common error in presentations, whether AI-generated or not, is excess text on each slide. The following guidelines should be followed:

    • 6 x 6 rule: A maximum of six bullet points per slide and six words per bullet.
    • One idea per slide. A slide that covers two topics should be split into two slides.
    • Allow visuals to breathe. White space is not wasted space; it is design.
    • Use the speaker notes for detail. A slide is a visual aid, not a document. Details should be placed in the notes and spoken aloud.

    The principles should be stated to Claude at the outset, for example: “Follow the 6×6 rule. Keep slides minimal. Place detailed information in the speaker notes rather than on the slides.”

    Add Custom Data Visualisations

    Although python-pptx can produce basic charts and Cowork can use PowerPoint’s built-in chart tools, the most important visualisations deserve dedicated attention. Options include:

    • Creating charts in Excel or Google Sheets first and then pasting them into the deck.
    • Using Python libraries such as matplotlib or plotly to generate chart images, which are then inserted into slides.
    • Using dedicated data visualisation tools such as Tableau or Power BI for complex dashboards, with the relevant views captured as screenshots.

    Claude can be asked to generate the chart code separately:

    Generate a matplotlib chart showing our revenue trend:
    Q1 2025: $2.1M, Q2: $2.8M, Q3: $3.1M, Q4: $3.6M, Q1 2026: $4.2M
    
    Style it with our brand colors. Save as revenue_chart.png at 300 DPI.
    Then insert it into slide 3 of the presentation.

    Version-Control Presentation Code

    For users of the python-pptx method, presentation scripts should be treated as any other code:

    • Scripts should be kept in a Git repository.
    • Meaningful file names should be used, for example q1_2026_qbr.py rather than presentation.py.
    • Data inputs should be parameterised so that the same script can generate decks for different quarters.
    • A short README explaining how to run each script should accompany the scripts.

    The practice is particularly valuable for recurring presentations: a Q2 deck is only a data update away from the Q1 script.

    Use an Iterative Approach

    It is not advisable to attempt a perfect presentation in a single prompt. Instead, the following passes are recommended:

    1. First pass: Generate the structure and core content.
    2. Second pass: Refine the narrative. Claude should be asked to improve flow, strengthen the opening, and sharpen the conclusion.
    3. Third pass: Polish the design, adjust colours, fix alignment, and ensure consistency.
    4. Final pass: Add speaker notes, verify data, and conduct a full review.

    Each pass takes a fraction of the time required to produce everything from scratch, and the iterative approach yields substantially better results than attempting to achieve everything in a single attempt.

    Final Thoughts

    Creating presentations has long been a task that many professionals dread: time-consuming, creatively demanding, and often producing underwhelming results. Claude Cowork substantially changes this calculus.

    With three distinct methods available—direct computer use for hands-off creation, python-pptx for programmatic precision, and structured outlines for creative control—the appropriate approach can be matched to each situation. A quick internal update may warrant the speed of computer use. A recurring board deck calls for a parameterised Python script. A high-stakes keynote benefits from Claude’s strategic outline combined with a personal design touch.

    The key insight is that Claude Cowork is not merely a presentation tool but a general-purpose AI agent that happens to be effective at presentations. It can research a topic, analyse data, write content, build slides, and automate the entire process on a schedule. No other single tool offers that breadth.

    The recommended starting point is a simple deck. The computer use method should be tried first to observe Claude opening PowerPoint and building slides in real time. Python-pptx can then be explored for a data-driven report. The eight hours per week spent on manual creation will soon appear unnecessary.

    The next strong presentation is one prompt away.

    References

  • Claude Cowork: Anthropic’s Desktop AI Agent That Works While You Sleep

    Summary

    What this post covers: A detailed examination of Claude Cowork, Anthropic’s desktop-first autonomous agent launched on 16 January 2026, including its capabilities, the January-March 2026 release timeline, the manner in which it differs from Claude Code, pricing, real-world use cases, and the competitive landscape.

    Key insights:

    • Cowork is positioned for non-technical knowledge workers, while Claude Code targets developers. Both run on the same Claude models, but Cowork emphasizes desktop control, Google Drive and Gmail integration, and phone dispatch rather than a CLI or IDE workflow.
    • The March 2026 computer-use update is the inflection point: Cowork can now click through GUIs, fill forms, and use applications that have no API, substantially expanding what can be automated beyond integration-supported tools.
    • Persistent Projects and scheduled tasks are the features that cause Cowork to function as a colleague rather than a chatbot. It retains context across sessions, dispatches work from a phone, and runs jobs overnight on a schedule.
    • At $20 per month for the Pro tier, the return-on-investment calculation is favourable for any user whose recurring research, reporting, or email-triage work consumes several hours per week. Those hours, rather than the subscription cost, represent the real expense being reduced.
    • Cowork remains a research preview: computer use can be unreliable on complex interfaces, the integration list is incomplete, and human oversight remains essential for any high-stakes deliverable.

    Main topics: What Is Claude Cowork?, Key Features That Define Cowork, Claude Cowork and Claude Code, Real-World Use Cases Across Industries, Pricing and Plans, How Cowork Compares with the Competition, Getting Started with Claude Cowork, Limitations and Considerations, Likely Future Directions for Cowork, Conclusion, References.

    Consider the experience of waking to find a weekly competitive analysis already compiled, the inbox triaged and summarized, and a polished research brief on the desktop, all completed overnight by an AI agent dispatched from a mobile device the prior evening. This scenario is not science fiction. As of early 2026, it describes an available product. The product is called Claude Cowork, and it represents one of the most significant shifts in how non-technical professionals interact with artificial intelligence.

    Anthropic, the AI safety company behind the Claude family of models, launched Cowork as a research preview on 16 January 2026. Subsequent substantial updates in February and March 2026 have transformed it from a promising experiment into a tool that materially changes daily workflow for knowledge workers. Unlike traditional AI chatbots that require user attention at every step of a complex task, Cowork operates autonomously, executing multi-step workflows on the desktop computer while the user attends to higher-value work, or while the user sleeps.

    This article examines in detail what Claude Cowork is, how it operates, the audience for which it is designed, the manner in which it differs from both Claude Code and competing products, and the procedure for beginning to use it. Readers who are researchers, analysts, operations managers, or any other professionals who spend substantial time on repetitive knowledge work will find a complete description here.

    What Is Claude Cowork?

    Claude Cowork is a desktop-first AI agent that brings agentic capabilities to non-technical users through the Claude desktop application. It functions as a capable virtual assistant that resides on the user’s computer and can perform actions rather than only suggesting what should be done.

    The traditional AI assistant model proceeds as follows: the user asks a question, receives an answer, acts on it, returns with a follow-up, and so on. Each step requires active user involvement. Cowork breaks this pattern entirely. The user describes a task, such as “Research the top five competitors in the European EV charging market, compile their latest quarterly results, and create a comparison table in a Google Doc,” and Cowork executes the entire workflow from start to finish.

    Key Takeaway: Claude Cowork is not a chatbot. It is an autonomous agent that executes multi-step tasks on the user’s desktop, accessing files, browsers, and tools without requiring intervention at each step.

    The term “Cowork” is deliberate. Anthropic designed this product to function as a skilled colleague seated at a virtual desk beside the user. Tasks are delegated to it as they would be to a team member, with context, instructions, and the expectation that the work will be completed. The distinction is that this colleague operates at machine speed, retains instructions perfectly, and is available continuously.

    The Research Preview Timeline

    Cowork’s development has progressed rapidly since its initial launch:

    Date Milestone Key Additions
    January 16, 2026 Research Preview Launch Core agentic workflows, local file access, Projects
    February 2026 Integration Expansion Google Drive, Gmail, scheduled tasks, phone dispatch
    March 2026 Computer Use Update Full desktop control, browser automation, expanded tool integrations

     

    Each update has meaningfully expanded Cowork’s capabilities. The March 2026 computer use update was particularly significant, as it gave Cowork the ability to interact directly with the computer’s graphical interface, opening applications, clicking buttons, filling forms, and navigating websites in the manner of a human user.

    Key Features That Define Cowork

    The following sections examine the features that define Claude Cowork and make it genuinely useful in day-to-day work.

    Multi-Step Task Execution

    This is the foundational capability that distinguishes Cowork from a standard chatbot. Given a complex task, Cowork decomposes it into steps, executes each one, handles errors and edge cases, and delivers a completed result.

    Consider the task of preparing a board-meeting brief. With a traditional AI assistant, the following sequence is required:

    1. Ask for a summary of recent financial performance
    2. Copy that output somewhere
    3. Ask for a competitive landscape overview
    4. Copy that too
    5. Ask for key risk factors
    6. Manually compile everything into a document
    7. Format it properly

    With Cowork, the user issues a single instruction: “Prepare my Q1 board meeting brief using the financial data in my Google Drive, our competitor tracker spreadsheet, and the risk register document. Format it as a polished PDF with our standard template.” Cowork then autonomously accesses each source, synthesizes the information, formats the document, and saves the finished product to the specified location.

    Computer Use (March 2026)

    The March 2026 update introduced full computer use capabilities, a transformative addition. Cowork can now perform the following actions:

    • Open and interact with desktop applications: word processors, spreadsheets, presentation software, email clients
    • Navigate web browsers: search the web, log into services, fill out forms, download files
    • Manipulate files: create, move, rename, and organize files and folders on the user’s system
    • Use specialized tools: interact with industry-specific software that does not provide an API integration

    This functionality is what makes Cowork resemble a colleague rather than software. It can use the computer as a person would, clicking through interfaces, reading the screen, and taking appropriate actions. The implications for automation are considerable, because Cowork is not limited to applications with built-in API integrations. If a human can use an application through a graphical interface, Cowork can typically do so as well.

    Claude Cowork Architecture User (Phone / Desktop) Tasks Claude Desktop AI Agent Core Projects · Scheduling Controls Computer Use 🖥 Screen Vision 🖱 Mouse / Click ⌨ Keyboard Input Operates Browsers Office Apps Cloud Services Results returned to user Gmail · Drive · FactSet DocuSign · Web Search

    Caution: Computer use remains in its early stages. While capable, it occasionally misclicks or misreads screen elements. The output of computer-use tasks should always be reviewed, particularly for high-stakes work such as financial transactions or legal documents.

    Local File Access

    Among Cowork’s most practical features is its ability to read and write local files without the friction of manual uploads and downloads. Previous AI workflows required users to copy-paste text, upload documents to a web interface, wait for processing, and download the results. Cowork accesses the local file system directly.

    The user can therefore direct Cowork at a folder of PDFs with an instruction such as “Summarize each document and create a master index,” and Cowork will process them in sequence without any manual file handling. For professionals who handle large volumes of documents (legal teams reviewing contracts, analysts processing earnings reports, researchers compiling literature reviews) this provides a substantial time saving.

    Task Dispatch from a Phone

    This is where the “works while the user sleeps” claim becomes literal. The user can message Claude from a phone, describe a task, and Cowork will execute it on the desktop computer. The desktop does not need to be actively in use; provided it is powered on and connected, Cowork can operate.

    Consider the following scenario: while commuting home on the train, the user recalls the need for a summary of all customer-feedback emails from the past week for the following morning’s meeting. The user opens the phone and messages Claude: “Go through my Gmail, find all customer feedback emails from the past seven days, categorize the feedback by theme, and create a summary document on my desktop.” By the time the user arrives home, the work is complete.

    Tip: For phone-dispatched tasks to operate reliably, the desktop Claude application should be running and the computer should not be in sleep mode. System power settings can be configured to prevent sleep during working hours.

    Scheduled Tasks

    Cowork supports scheduled tasks: recurring automated workflows that run on a defined cadence. Some useful examples include:

    • Daily morning briefing: Every day at 7 AM, Cowork compiles overnight news relevant to your industry, checks your calendar for the day, and generates a one-page briefing document
    • Weekly report generation: Every Friday at 4 PM, Cowork pulls data from your tracking spreadsheets and generates a formatted weekly status report
    • Automated file processing: Whenever new files appear in a designated folder, Cowork processes them according to your instructions—extracting data, reformatting, or routing to the appropriate location
    • Email digests: Twice daily, Cowork scans your inbox, identifies high-priority items, and sends you a categorized summary

    This scheduled-task functionality moves Cowork from a reactive tool (the user asks, the tool acts) to a proactive one (the tool acts automatically according to user-defined rules). For teams with repetitive operational workflows, this capability alone can justify the subscription cost.

    Cowork Agentic Workflow Loop Task Assignment User defines goal via chat or phone Screen Observation Claude reads current app / browser state Action Taken Click · Type · Navigate API call · File write Verify Did it work? Check result Loop: re-observe if task incomplete Done → Deliver result 1 2 3 4

    Projects: Persistent Workspaces

    Projects are persistent workspaces within Cowork in which files, links, instructions, and context can be stored. The agent retains this material across sessions. A Project may be understood as a briefing folder for a specific area of work.

    For example, a user might create a Project titled “Competitive Intelligence” containing the following:

    • Links to competitor websites and press pages
    • Your company’s competitive positioning document
    • Instructions on how you want competitive updates formatted
    • Previous reports for style reference
    • A list of key metrics to track

    When the user requests any task within that Project, this context is immediately available. There is no need to re-explain preferences or re-upload reference documents on each occasion. The agent accumulates institutional knowledge over time and becomes more useful with continued use within a given Project.

    Tool Integrations

    Cowork connects with a growing list of third-party services through direct integrations:

    Category Integrations Key Capabilities
    Productivity Google Drive, Google Docs, Google Sheets Read, create, and edit documents and spreadsheets
    Communication Gmail Read, search, and draft emails
    Legal / Contracts DocuSign Prepare and route documents for signature
    Finance / Data FactSet Pull financial data, market metrics, and analytics
    Web Research Built-in web search Search the web and internal document repositories

     

    These integrations enable Cowork to execute end-to-end workflows that span multiple tools. A single task might involve retrieving data from FactSet, researching context on the web, creating a formatted report in Google Docs, and emailing the finished product via Gmail, all without the user touching any of these applications.

    Web Research

    Cowork can search both the open web and internal document repositories. This dual capability is particularly valuable for research tasks that require the combination of public information (market data, news, academic papers) with proprietary internal knowledge (company reports, internal wikis, prior analyses).

    The web-research capability extends beyond simple search. Cowork can visit multiple pages, extract relevant information, cross-reference sources, and synthesize findings into coherent analysis. For research-intensive roles, this can compress hours of manual research into minutes.

    Claude Cowork and Claude Code: Understanding the Difference

    Readers already familiar with Claude Code may wonder how Cowork relates to it. The answer is straightforward: they are designed for fundamentally different users and use cases.

    Dimension Claude Code Claude Cowork
    Interface Command-line terminal (CLI) Desktop application (GUI)
    Primary users Software developers, DevOps engineers Knowledge workers, analysts, researchers, operations teams
    Core capability Write, debug, and deploy code Execute knowledge work tasks across desktop tools
    Technical requirement Terminal proficiency required No terminal or coding skills needed
    Execution environment Shell, filesystem, git, package managers Desktop apps, browsers, cloud services
    Typical task “Refactor this module and write tests” “Compile a competitive analysis from these sources”
    Computer use No (operates via CLI) Yes (can control desktop GUI)
    Phone dispatch No Yes
    Scheduled tasks Via cron/CI (manual setup) Built-in scheduling feature

     

    The distinction may be summarized as follows: Claude Code is for users who work primarily in the terminal; Claude Cowork is for users who work primarily in documents, spreadsheets, and email.

    There is some overlap. Both products can access local files, both can perform research, and both can execute multi-step tasks autonomously. The execution environment and target user profile, however, differ entirely. A software engineer building a web application requires Claude Code. A financial analyst constructing an investment thesis requires Claude Cowork.

    Many advanced users will require both. A startup CTO might use Claude Code for development work during the day and Claude Cowork for business planning, investor communications, and market research. The two products complement rather than compete with one another.

    Key Takeaway: Claude Code and Claude Cowork are companion products rather than competitors. Code targets developers through the CLI; Cowork targets knowledge workers through a desktop GUI. The choice should be guided by workflow, and both can be used together.

    Claude Code vs. Claude Cowork—Side by Side Claude Code Interface Command-line (CLI) Users Developers Core task Write & debug code Environment Shell / Git / FS Computer Use No Phone dispatch No Technical proficiency required Claude Cowork Interface Desktop app (GUI) Users Knowledge workers Core task Research · Docs · Email Environment Apps / Browsers / Cloud Computer Use Yes Phone dispatch Yes No coding skills needed VS

    Real-World Use Cases Across Industries

    The most effective method of understanding Cowork’s value is through concrete examples. The following detailed use cases span several professional domains.

    Research and Analysis

    A market-research analyst must compile a report on the state of autonomous-vehicle regulation across ten countries. Traditionally, this task requires two to three days of manual research, reading regulatory documents, cross-referencing sources, and constructing comparison tables.

    With Cowork, the analyst creates a Project titled “AV Regulation Research” and provides instructions: which countries to cover, which regulatory dimensions to compare, the desired output format, and links to key regulatory-body websites. Cowork then performs the following steps:

    1. Searches the web for the latest regulatory developments in each country
    2. Accesses government regulatory databases where available
    3. Reads through the analyst’s existing internal research documents in Google Drive
    4. Cross-references all sources to build a comprehensive comparison
    5. Creates a formatted report with comparison tables, source citations, and an executive summary
    6. Saves the finished document to Google Drive and emails the analyst a notification

    A task that previously required days is completed in hours, and the analyst’s expertise is applied to reviewing and refining the output rather than to manual data collection.

    Financial Analysis

    An investment analyst must prepare earnings-season coverage for a portfolio of twenty technology stocks. For each company, the analyst requires a summary of the earnings call, key financial metrics versus consensus, changes in management guidance, and a brief assessment of the quarter.

    Cowork can retrieve data from FactSet, search the web for earnings-call transcripts and analyst commentary, compile metrics into standardized comparison tables, and generate individual company summaries together with a portfolio-level overview. The analyst can schedule this work to run automatically as each company reports, so that summaries are available the following morning.

    A legal team must review a set of vendor contracts for compliance with new data-privacy regulations. Each contract must be checked against a specific checklist of required clauses, and any gaps must be flagged.

    Cowork can read each contract PDF, compare the terms against the compliance checklist stored in the Project, generate a gap analysis for each contract, and compile a summary report identifying compliant vendors and those that require contract amendments. For the non-compliant contracts, Cowork can also draft amendment language based on the team’s standard templates.

    Operations and Administration

    An operations manager runs a weekly process that requires downloading sales data from a CRM, combining it with inventory data from a separate system, generating a forecast update, and distributing it to regional managers. This process consumes three to four hours each week and involves multiple tools.

    With Cowork’s scheduled-task feature, the entire workflow runs automatically every Friday. Cowork accesses the necessary systems (using computer use for applications without API integrations), processes the data, generates the forecast in the standard template, and emails the results to the distribution list. The operations manager reviews the output and approves the dispatch, a ten-minute task in place of a four-hour one.

    Email Management

    A senior executive receives two hundred or more emails per day. Most are informational, some require responses, and a few are genuinely urgent. Sorting through them constitutes a daily time sink.

    Cowork can be configured to perform a twice-daily email triage: read all incoming emails, categorize them by priority and topic, draft responses for routine items (which the executive reviews before sending), flag truly urgent items for immediate attention, and generate a summary document indicating what has arrived and what requires action. This converts email management from an hour-long chore into a focused fifteen-minute review.

    Quick Reference: Task Examples

    Task Traditional Approach With Cowork Time Saved
    Weekly competitive report 4–6 hours manual research Automated, 20 min review ~80%
    Earnings call summaries (20 stocks) 2–3 days of reading/writing Overnight batch processing ~85%
    Contract compliance review (10 docs) 1–2 days legal review 2–3 hours + review ~70%
    Daily email triage (200+ emails) 60–90 minutes per day 15-minute review ~75%
    Market research report 2–3 days research and writing 4–6 hours + review ~65%
    Weekly operations forecast 3–4 hours manual processing Automated, 10 min review ~90%

     

    Pricing and Plans

    Anthropic offers Claude Cowork as part of its broader Claude subscription tiers. The current pricing structure is as follows:

    Plan Price Cowork Access Best For
    Pro $20/month Basic Cowork features, limited task runs Individual professionals testing agentic workflows
    Max $100–$200/month Full Cowork with higher limits, priority execution Power users running frequent or complex workflows
    Team $30/user/month Cowork with team sharing, shared Projects Small to mid-size teams collaborating on workflows
    Enterprise Custom pricing Full Cowork, SSO, audit logs, admin controls, custom integrations Large organizations with compliance and security requirements

     

    For most individuals, the Pro plan at twenty dollars per month is a reasonable starting point for exploring Cowork’s capabilities. Users who routinely encounter usage limits or operate complex multi-tool workflows will find that the Max tier removes those constraints. Teams that require shared Projects and collaborative workflows should consider the Team plan, while enterprises with specific compliance requirements will require the custom Enterprise tier.

    Tip: A starting point on the Pro plan permits evaluation of Cowork for specific use cases. Users can upgrade to Max or Team once they understand how Cowork fits into their workflow and how much capacity they require. Overcommitment in the first month is unnecessary.

    The value proposition becomes clear when the subscription cost is compared to the time savings. If Cowork saves an analyst even five hours per week, a conservative estimate based on the use cases described above, that amounts to approximately twenty hours per month. At a fully loaded cost of fifty to one hundred dollars per hour for a knowledge worker, the monthly savings exceed even the Max plan’s subscription fee. The economics are compelling even at modest adoption levels.

    How Cowork Compares with the Competition

    Claude Cowork does not exist in isolation. Microsoft, Google, and OpenAI each have competing visions for AI-assisted work. The following table compares the principal offerings.

    Feature Claude Cowork Microsoft Copilot Google Gemini Workspace OpenAI Desktop App
    Autonomous multi-step tasks Strong Moderate Moderate Basic
    Computer use (GUI control) Yes No No Limited
    Local file access Yes Via OneDrive/SharePoint Via Google Drive Limited
    Phone dispatch Yes No No No
    Scheduled tasks Built-in Via Power Automate Limited No
    Persistent workspaces Projects Notebooks Gems Custom GPTs
    Ecosystem lock-in Low (cross-platform) High (Microsoft 365) High (Google Workspace) Low
    Third-party integrations Growing (FactSet, DocuSign, etc.) Deep Microsoft ecosystem Deep Google ecosystem Limited
    Underlying model quality Claude (top-tier reasoning) GPT-4 variants Gemini models GPT-4 variants

     

    Areas in Which Cowork Excels

    Cowork’s principal advantages are its computer-use capability, phone dispatch, and low ecosystem lock-in. Microsoft Copilot performs well for organizations entirely within the Microsoft 365 ecosystem, but it struggles with tools outside that environment. Google Gemini exhibits the same limitation: capable within Google Workspace but constrained outside it. Cowork’s computer-use feature enables operation with virtually any application, regardless of whether a formal integration exists.

    The phone-dispatch feature is also unique among current competitors and represents a genuine workflow innovation. The ability to conceive a task away from one’s desk and immediately dispatch it for execution is not currently available from the major competitors.

    Areas in Which Competitors Excel

    Microsoft Copilot benefits from deep, native integration with the most widely used office suite. For organizations operating on Microsoft 365, Copilot’s integration with Word, Excel, PowerPoint, Teams, and Outlook is seamless in a way that Cowork cannot fully replicate through external integrations alone.

    Similarly, for organizations fully committed to Google Workspace, Gemini’s native integration provides a smoother experience for tasks that remain within the Google ecosystem. The experience of using Gemini inside a Google Doc or Sheet is more refined than having an external agent interact with those same tools.

    OpenAI’s desktop app, while currently the least capable of the four in terms of agentic features, benefits from GPT-4’s strong general capabilities together with OpenAI’s substantial user base and brand recognition.

    The Principal Differentiator: Agent-First Design

    The aspect that most distinguishes Cowork is its agent-first design philosophy. Microsoft and Google added AI capabilities on top of existing productivity suites. Copilot is essentially an intelligent overlay on Office, and Gemini is an intelligent overlay on Workspace. Cowork was built from the outset as an autonomous agent. The difference is evident in how it handles complex, multi-step workflows that span multiple tools and data sources.

    When a task requires retrieving data from three sources, combining it, applying analysis, and distributing results across two platforms, Cowork’s agent architecture handles this naturally. Copilot and Gemini, designed primarily for in-app assistance, can struggle with workflows that cross application boundaries.

    Getting Started with Claude Cowork

    The following step-by-step procedure describes how to begin using Cowork.

    Enable Cowork in the Claude Desktop App

    1. Download Claude Desktop. If it is not already installed, the Claude desktop application should be downloaded from claude.ai. It is available for macOS and Windows.
    2. Subscribe to a paid plan. Cowork requires at least a Pro subscription ($20 per month). Log into the Claude account and upgrade if necessary.
    3. Enable Cowork. Open the Claude desktop application, navigate to Settings, and locate the Cowork section. Toggle it on. Additional permissions for local file access and computer use may be required.
    4. Grant permissions. Cowork will request permissions to access the filesystem, the screen, and any integrations to be used. These should be reviewed carefully, and only the relevant ones should be enabled.
    Caution: Granting computer-use permissions allows Cowork to control the mouse and keyboard. This capability should be enabled only for tasks in which automated desktop control is acceptable, and the agent’s actions should always be reviewed for sensitive operations.

    Set Up the First Task

    A simple task is appropriate as the first exercise. The following is a suitable example:

    Task: "Read the PDF files in my Documents/Reports folder,
    create a one-paragraph summary of each, and compile them
    into a single document called 'Report Summaries' on my Desktop."

    This task exercises several Cowork capabilities, namely local file access, document reading, text generation, and file creation, while remaining low-stakes enough that the user can readily verify the output.

    As familiarity grows, more complex tasks can be attempted:

    • Week 1: Simple file processing and summarization tasks
    • Week 2: Multi-source research tasks (combine web research with local documents)
    • Week 3: Set up your first Project with persistent context
    • Week 4: Configure scheduled tasks and try phone dispatch

    Configure Integrations

    To obtain maximum value from Cowork, the services used daily should be connected:

    1. Google Drive: Settings > Integrations > Google Drive > Authorize. This grants Cowork read/write access to Drive files.
    2. Gmail: Settings > Integrations > Gmail > Authorize. This enables email reading, searching, and drafting.
    3. Additional services: The Integrations panel should be reviewed for newly added services. Anthropic is adding integrations regularly during the research preview.

    Create the First Project

    Projects are the mechanism through which Cowork’s value compounds over time. The procedure for creating one is as follows:

    1. Open the Claude desktop application and navigate to the Projects section.
    2. Click “New Project” and provide a descriptive name.
    3. Add relevant files, links, and reference documents.
    4. Write a set of instructions describing preferences, standards, and common tasks for the domain.
    5. Begin assigning tasks within the Project context.

    A well-configured Project substantially improves Cowork’s output quality because the agent has all the context required to produce work that matches the user’s standards and preferences.

    Tip: Examples of past work should be included in Projects. If Cowork is to produce weekly reports, two or three examples of well-prepared past reports should be uploaded. Cowork learns style and formatting preferences from these examples.

    Set Up Scheduled Tasks

    Once a task is ready to run regularly, the following procedure applies:

    1. Run the task manually first to confirm that it produces the desired output.
    2. Open the task and click “Schedule” (or create a new scheduled task).
    3. Set the frequency (daily, weekly, or a custom cron expression).
    4. Set the time of day for execution.
    5. Choose whether to receive a notification on task completion.
    6. Optionally set conditions, for example, run only if new files are present in a specific folder.

    One or two scheduled tasks form a reasonable starting point, with expansion from there. A few reliable automated workflows are preferable to a dozen unreliable ones.

    Limitations and Considerations

    No product review is complete without an honest assessment of limitations. Cowork, still in research preview, has several important limitations.

    Research Preview Status

    As of April 2026, Cowork remains labelled as a research preview. The implications are as follows:

    • Features may change, be removed, or be restructured
    • Reliability, while generally good, is not at production-grade levels for all features
    • Rate limits and usage caps may shift as Anthropic refines pricing
    • Some integrations are early-stage and may have rough edges

    For critical business processes, human oversight should be retained, and exclusive reliance on Cowork for time-sensitive deliverables should be avoided until the product exits research preview.

    Privacy and Data Considerations

    Granting Cowork access to local files, email, and cloud storage entails providing an AI system with access to potentially sensitive information. Key considerations include the following:

    • Data handling: Anthropic’s data-retention policies should be understood. The privacy documentation indicates what data is stored, for how long, and how it is used.
    • Sensitive documents: Care should be exercised in selecting files and folders to which access is granted. Specific folder permissions can be configured rather than blanket filesystem access.
    • Email access: Gmail integration permits Cowork to read emails. Whether the inbox contains information that should not be processed by an AI system should be considered.
    • Computer-use recording: When computer use is active, Cowork captures screenshots to understand the screen contents. This should be borne in mind when sensitive information is displayed.
    Caution: Enterprise users should coordinate with their IT and security teams before deploying Cowork. The Enterprise plan includes SSO, audit logs, and administrative controls designed for organizations with strict data-governance requirements.

    What Cowork Cannot Do at Present

    • Real-time collaboration: Cowork operates asynchronously. It cannot join a live meeting and take notes in real time, although it can process meeting recordings after the fact.
    • Physical actions: It can control the computer but cannot perform any action in the physical world; it cannot print, sign physical documents, or manage physical inventory.
    • Perfect accuracy on all tasks: As with all AI systems, Cowork can make mistakes. It may misinterpret instructions, miss nuances in documents, or produce inaccurate summaries. Human review remains essential.
    • Highly specialized domain work: Although Cowork performs well on general knowledge work, tasks that require deep domain expertise (advanced scientific analysis, complex legal strategy, nuanced medical interpretation) continue to require expert human oversight.
    • Cross-organization workflows: Cowork operates within the user’s own systems and accounts. It cannot directly interact with a colleague’s computer or access systems for which the user lacks credentials.

    Setting Reliability Expectations

    In practice, Cowork handles straightforward multi-step tasks with high reliability. File processing, research compilation, report generation, and similar workflows succeed consistently. More complex tasks involving computer use, particularly those that navigate unfamiliar or complex user interfaces, exhibit higher failure rates. The recommendation is to begin with simpler tasks and gradually increase complexity as the system’s capabilities and boundaries are understood.

    Likely Future Directions for Cowork

    Although Anthropic has not published a detailed public roadmap for Cowork, several directions appear likely based on the trajectory of updates and broader industry trends.

    Expanded Integrations

    The current integration list (Google Drive, Gmail, DocuSign, FactSet) is solid but narrow relative to the universe of business tools. Integrations with CRM platforms such as Salesforce and HubSpot, project-management tools such as Jira and Asana, communication platforms such as Slack and Microsoft Teams, and data-visualization tools such as Tableau and Power BI can be anticipated. Each new integration expands the range of end-to-end workflows that Cowork can automate.

    Improved Computer Use

    Computer use is Cowork’s most ambitious feature and the one with the most room for improvement. Future updates are likely to bring faster execution, more reliable interaction with complex UIs, improved error recovery, and support for additional applications and web interfaces. As this capability matures, it effectively removes the need for formal integrations for many applications: if Cowork can use the application through its GUI, a dedicated integration becomes optional rather than required.

    Enterprise Features

    Enterprise adoption requires features that individual users do not need: role-based access controls, detailed audit trails, data-loss-prevention policies, custom model fine-tuning, on-premises deployment options, and integration with enterprise identity-management systems. Substantial investment in this area is expected, since enterprise contracts represent the most significant revenue opportunity for AI platform companies.

    Multi-Agent Collaboration

    A particularly notable possibility is multi-agent workflows in which several Cowork agents collaborate on a single task. A complex project such as preparing a company’s annual report might be assigned to multiple agents: one handling financial-data analysis, another market research, a third competitor analysis, and a coordinating agent assembling the final document. This divide-and-conquer approach to knowledge work could substantially expand the scope and complexity of tasks Cowork can handle.

    Learning and Adaptation

    Over time, Cowork should improve at understanding individual users’ preferences, work styles, and quality standards. The Projects feature already enables some of this through explicit instructions and examples. Future versions may learn more implicitly, recognizing, for example, that the user consistently prefers tables to bullet points, prefers executive summaries to be a single paragraph, or prefers financial figures rounded to one decimal place. Such passive learning could substantially reduce the amount of upfront configuration required.

    Conclusion

    Claude Cowork represents a genuine advance in how non-technical professionals can use AI. It is not merely another chatbot with a new interface. It is a fundamentally different approach to AI-assisted work: an autonomous agent that resides on the desktop, understands the user’s context through persistent Projects, connects to tools through integrations and computer use, and operates even when the user is not actively directing it.

    The principal innovations (multi-step task execution, computer use, phone dispatch, scheduled tasks, and persistent Projects) combine to create something that resembles a digital colleague more than a tool. The practical impact is real: tasks that traditionally consumed hours or days of manual work can be completed in a fraction of the time, with the user’s expertise focused on review, refinement, and decision-making rather than on data gathering and formatting.

    Is Cowork without limitations? No. It remains in research preview; computer use can be unreliable on complex interfaces; the integration list is still expanding; and human oversight remains essential for high-stakes work. The trajectory, however, is clear. Each monthly update has brought meaningful improvements, and the foundation (an agent-first architecture combined with one of the most capable language models available) is strong.

    For knowledge workers who spend substantial time on research, report generation, data compilation, email management, or document processing, Cowork is worth evaluating now. A Pro subscription can be used to build a Project around the most time-consuming recurring task, and the resulting time savings can be measured. The twenty-dollar monthly investment can readily return hundreds of dollars in reclaimed productive hours.

    The era of AI that waits for the next prompt is yielding to an era of AI that works alongside the user, and at times in advance of the user. Claude Cowork is one of the most compelling products driving that transition.

    References

    Disclaimer: This article is for informational purposes only and does not constitute investment advice. Product features, pricing, and availability may change. Always verify current details directly with Anthropic before making purchasing decisions.

  • Claude in 2026: Everything New in Anthropic’s Most Powerful AI Model Family

    Summary

    What this post covers: A comprehensive 2026 examination of the Claude ecosystem: the Opus/Sonnet/Haiku model family, Claude Code, extended thinking, MCP, the API/SDK, safety practices, and Claude’s position relative to GPT-4o, Gemini 2.5, Llama 4, and DeepSeek.

    Key insights:

    • Claude Opus 4.6 currently leads composite benchmarks on coding (SWE-bench Verified), scientific reasoning (GPQA Diamond), and mathematics (MATH-500), placing Anthropic, rather than OpenAI or Google, at the frontier of reasoning quality in early 2026.
    • The three-tier structure is a cost-and-quality routing mechanism rather than a hierarchy: Sonnet 4.6 ($3/$15 per M tokens) is the appropriate default for most production workloads, with Opus reserved for difficult reasoning and Haiku 4.5 for high-volume routing or classification.
    • Claude Code is the most concrete differentiator: an agentic CLI/IDE tool that autonomously navigates codebases, edits multiple files, runs tests, and commits, rather than offering Copilot-style inline suggestions.
    • The Model Context Protocol (MCP) is becoming a de facto industry standard for connecting LLMs to tools and data sources, and is the integration layer on which most enterprise Claude deployments are now built.
    • No single “best” model exists: Claude leads on coding and reasoning, Gemini on context length and Google integration, Llama and DeepSeek on cost and openness, and GPT-4o on multimodal breadth. Selection should be governed by workload rather than by brand.

    Main topics: Introduction, The Claude Model Family in 2026, Claude Code, Extended Thinking, Tool Use and Function Calling, Model Context Protocol, API and SDK, Safety and Alignment, Real-World Applications, Comparison with Competitors, Conclusion, References.

    Introduction: Why Claude Matters More Than Ever

    In January 2026, a research organization with fewer than 1,500 employees surpassed a major search-engine company and a firm previously valued at over a trillion dollars in what may be the most consequential AI benchmark sequence in recent memory. Anthropic’s Claude Opus 4.6 achieved the highest composite result yet recorded on SWE-bench Verified, GPQA Diamond, and MATH-500, and did so by a substantial margin. For the first time, a single model family delivered the best performance across coding, scientific reasoning, and mathematical problem-solving simultaneously.

    This result is not merely a benchmark curiosity. It reflects a fundamental shift in how AI is built, deployed, and used by millions of developers, researchers, analysts, and businesses worldwide. Claude is no longer simply the “safety-focused alternative” to ChatGPT. By a range of measures it is currently the most capable large language model available, and Anthropic has constructed an ecosystem around it that extends well beyond a chatbot interface.

    Developers who have not used the Claude API since 2024 are working with outdated assumptions. Investors tracking the AI landscape will benefit from understanding what Anthropic has built and where it is heading. Those who simply use AI tools daily will find that the Claude of early 2026 is a substantially different product from what existed even twelve months earlier.

    This article provides a comprehensive guide to recent developments in the Claude ecosystem. It examines the full model family (Opus, Sonnet, and Haiku) and the appropriate context for each. It examines in detail Claude Code, Anthropic’s agentic coding tool that is reshaping how software is built. It explores extended thinking, tool use, the Model Context Protocol, the API and SDK, safety practices, real-world applications, and the position of Claude relative to GPT-4o, Gemini 2.5, Llama 4, and DeepSeek.

    The following sections address both technical detail and the broader context.

    Key Takeaway: Claude in 2026 is more than a chatbot. It is a model family (Opus, Sonnet, Haiku) supported by an integrated ecosystem that comprises a coding agent, an open integration protocol, extended reasoning capabilities, and enterprise-grade APIs. This guide covers each of these elements.

     

    The Claude Model Family in 2026: Opus, Sonnet, and Haiku

    Anthropic organizes its Claude models into three tiers, each designed for different use cases, budgets, and latency requirements. The tiers can be understood as comparable to choosing among a high-performance vehicle, a balanced sedan, and an efficient commuter: each is capable of reaching the destination, but the trade-offs between power, speed, and cost differ.

    As of early 2026, the current generation is the 4.5/4.6 family, which represents Anthropic’s most advanced models to date. The following sections describe what each tier offers and the contexts in which it is appropriate.

    Claude Model Family Timeline v1 Claude 1 2023 v2 Claude 2 2023 v3 Claude 3 2024 Opus · Sonnet · Haiku 3.5 Claude 3.5 2024–25 v4 Claude 4 2025–26 Current Opus 4.6 · Sonnet 4.6

    Claude Opus 4.6: Anthropic’s Most Capable Model

    Claude Opus 4.6 (model ID: claude-opus-4-6) is Anthropic’s flagship. It is the appropriate choice when a task demands the highest possible reasoning quality and when additional cost and latency are acceptable.

    Opus 4.6 performs well on tasks that require multi-step reasoning: complex code architecture decisions, nuanced legal or financial document analysis, advanced mathematics, scientific research synthesis, and long-form writing that must maintain coherence across thousands of words. It is also the model powering the most advanced tier of Claude Code, where it autonomously navigates large codebases, writes tests, refactors modules, and commits changes.

    What distinguishes Opus from its predecessors is not only raw capability but reliability. Earlier generations of large language models, including previous Claude versions, occasionally produced confidently incorrect answers on complex tasks. Opus 4.6 demonstrates a marked improvement in recognizing the limits of its knowledge, qualifying uncertain statements, and requesting clarification rather than guessing. This matters considerably in production environments where an AI hallucination can be costly.

    The context window is 200,000 tokens, which corresponds to approximately 500 pages of text or an entire mid-sized codebase. With extended context options, certain configurations support up to 1 million tokens, allowing Opus to ingest and reason over substantial documents or repositories in a single conversation.

    Tip: For applications in which accuracy on complex reasoning is mission-critical (for example, code review for a financial trading system or summarization of a 200-page legal contract), Opus 4.6 justifies its premium. For most other use cases, Sonnet is the more appropriate default.

    Claude Sonnet 4.6: A Balanced Default

    Claude Sonnet 4.6 (model ID: claude-sonnet-4-6) is the appropriate default model for most developers and businesses. It offers a balanced combination of capability and speed, performing within a few percentage points of Opus on most benchmarks while being substantially faster and less expensive.

    Sonnet handles the majority of real-world tasks effectively: writing and debugging code, answering complex questions, generating content, analyzing data, and powering chatbots. It is the model Anthropic recommends for most API integrations, and it is the default in the Claude.ai web interface and mobile applications.

    The principal advantage of Sonnet is its response latency. For interactive applications such as chat interfaces, coding assistants, and real-time analysis tools, the difference between Opus and Sonnet is observable. Sonnet typically responds two to four times more quickly, which substantially improves the user experience in tools where each response precedes the next action.

    Sonnet 4.6 also shares the 200,000-token context window of its larger counterpart, so selecting the faster model does not sacrifice the ability to work with large documents or codebases.

    Claude Haiku 4.5: Speed and Efficiency at Scale

    Claude Haiku 4.5 (model ID: claude-haiku-4-5-20251001) is Anthropic’s fastest and most cost-effective model. It is designed for high-volume, latency-sensitive applications that require rapid, competent responses at minimal cost.

    Haiku is well-suited to classification tasks, brief summarization, lightweight code generation, customer service chatbots, data extraction, and any scenario involving thousands or millions of API calls where cost control is important. Although it is the smallest model in the family, Haiku 4.5 is markedly capable and outperforms many competitors’ flagship models from the previous year.

    One pattern that has become increasingly common is the use of Haiku as a routing layer: a fast, inexpensive model that classifies incoming requests and decides whether to handle them directly or escalate to Sonnet or Opus. This arrangement delivers Opus-level quality on difficult problems and Haiku-level costs on routine ones.

    Key Takeaway: The three-tier model structure is not a “good, better, best” hierarchy. It is a mechanism for matching the appropriate model to the task at hand. Most teams use Sonnet as the default, escalate to Opus for difficult problems, and deploy Haiku for high-volume workloads.

    Model Comparison Table

    Feature Opus 4.6 Sonnet 4.6 Haiku 4.5
    Model ID claude-opus-4-6 claude-sonnet-4-6 claude-haiku-4-5-20251001
    Context Window 200K tokens (up to 1M) 200K tokens 200K tokens
    Best For Complex reasoning, research, advanced coding General-purpose, most API integrations High-volume, low-latency tasks
    Input Price $15 / M tokens $3 / M tokens $0.80 / M tokens
    Output Price $75 / M tokens $15 / M tokens $4 / M tokens
    Speed Moderate Fast Very Fast
    Extended Thinking Yes Yes Limited
    Tool Use Yes Yes Yes

     

    Claude Code: An Agentic Tool for Writing, Testing, and Shipping

    If the model family is the engine, Claude Code is the vehicle that places that capability directly in developers’ hands. Initially launched as a CLI tool in late 2024 and substantially expanded throughout 2025 and into 2026, Claude Code represents Anthropic’s vision of AI-assisted software development. It is not simply an autocomplete tool but a genuine coding agent that can autonomously navigate a codebase, write code, run tests, fix bugs, and commit changes.

    Claude Code is fundamentally different from tools such as GitHub Copilot, which primarily offer inline suggestions as a developer types. Claude Code operates at a higher level of abstraction. A user describes the desired outcome in natural language (“add pagination to the user list API endpoint,” “refactor this module to use dependency injection,” “find and fix the bug causing the login timeout”), and Claude Code determines which files to read, what changes to make, how to test them, and how to commit the result.

    Available Platforms

    As of early 2026, Claude Code is available across a wide set of platforms:

    • CLI (Command Line Interface): The original and most capable form. It is installed with npm install -g @anthropic-ai/claude-code and invoked by running claude in any project directory. The CLI provides full access to all features, including custom slash commands, hooks, and MCP server connections.
    • Desktop App (Mac and Windows): A standalone application that wraps the CLI experience in a native desktop interface. It is appropriate for developers who prefer a graphical environment while retaining the agentic workflow.
    • Web App (claude.ai/code): A browser-based version that connects to repositories via GitHub. It is suitable for short tasks or for use away from the primary development machine.
    • VS Code Extension: Deep integration with the most widely used code editor. Claude Code appears as a sidebar panel and can access the workspace, terminal, and source control.
    • JetBrains Extension: Similar integration for IntelliJ IDEA, PyCharm, WebStorm, and other JetBrains IDEs. It supports the same agentic workflows as the CLI.

    Claude Product Ecosystem Claude API & Models Claude.ai Web & Mobile Claude Code CLI · IDE · Web Desktop App Mac & Windows MCP Open Protocol Anthropic API

    Key Features

    Agentic Code Editing. Claude Code does not merely suggest changes; it implements them. When given a task, it reads the relevant files, plans an approach, writes or modifies code across multiple files, and can run the test suite to verify that the changes are correct. It operates in a loop: make changes, run tests, address any failures, and repeat until the task is complete.

    Custom Slash Commands. Teams can define reusable commands in .claude/commands/ directories. For example, a team might create a /deploy command that runs the deployment pipeline, a /review command that performs code review against the team’s style guide, or a /write-post command that orchestrates blog-post creation and publishing. These commands are version-controlled alongside the code, ensuring that the entire team shares the same workflows.

    Hooks System. Claude Code supports pre- and post-execution hooks that run before or after specific actions. Hooks can enforce coding standards, run linters, execute security checks, or trigger notifications. This integrates Claude Code into the CI/CD pipeline rather than leaving it as a standalone tool.

    MCP Server Integration. Through the Model Context Protocol (discussed in detail below), Claude Code can connect to external tools and data sources, including databases, APIs, documentation servers, and issue trackers. Claude Code can therefore look up a Jira ticket, inspect a database schema, read API documentation, and then write code that integrates the resulting context.

    Git Integration. Claude Code supports Git natively. It can create branches, stage changes, write commit messages, and create pull requests. Many developers now use Claude Code as their primary interface for Git operations, describing the intended commit in natural language and allowing Claude to handle the details.

    # Install Claude Code
    npm install -g @anthropic-ai/claude-code
    
    # Start a session in your project directory
    cd my-project
    claude
    
    # Example interactions inside Claude Code
    > Add comprehensive unit tests for the authentication module
    > Refactor the database layer to use connection pooling
    > Find the bug causing the 500 error on /api/users and fix it
    > Create a new REST endpoint for product search with pagination

    Claude Code Compared to Copilot, Cursor, and Windsurf

    The AI coding-tool market is crowded, and each product adopts a distinct approach. The following table compares Claude Code to the principal alternatives.

    Feature Claude Code GitHub Copilot Cursor Windsurf
    Primary Mode Agentic (autonomous) Inline suggestions + chat AI-native editor Flow-state IDE
    Underlying Models Claude (Opus, Sonnet) GPT-4o, Claude, Gemini Multi-model (user choice) Proprietary + GPT-4o
    Multi-File Editing Excellent Good (Workspace mode) Excellent (Composer) Good
    Terminal Integration Native (CLI-first) Limited Yes Yes
    Custom Commands Yes (slash commands) Limited Yes (rules) Limited
    MCP Support Full native support Partial Yes Limited
    Autonomous Testing Yes (runs tests, fixes) No Partial Partial
    Price (Pro Tier) $20/month (Claude Pro) $19/month (Pro) $20/month (Pro) $15/month (Pro)

     

    The fundamental difference is philosophical. GitHub Copilot is designed to assist a developer who remains at the controls; it is a co-pilot in the strict sense. Cursor is an AI-native editor that blurs the line between writing code manually and having AI write it. Claude Code is an autonomous agent to which tasks are delegated. The developer specifies what to build, and Claude Code builds it.

    In practice, many developers use multiple tools. A common pattern uses Claude Code for large-scale tasks (new features, refactoring, complex bug fixes) and Copilot or Cursor for the moment-to-moment inline coding experience. The tools are not mutually exclusive.

    Tip: Users new to AI coding tools can begin with Claude Code’s web version at claude.ai/code. It requires no installation and provides familiarity with the agentic workflow. The CLI can then be installed once the full experience is appropriate.

     

    Extended Thinking: How Claude Reasons Through Difficult Problems

    One of Claude’s most capable and underappreciated features is extended thinking, which allows the model to devote additional time to reasoning through a problem before generating a response. This is not merely a matter of taking longer to answer. It is a fundamentally different mode of operation that produces substantially improved results on complex tasks.

    When extended thinking is enabled, Claude generates an internal chain of thought before producing its visible response. This chain of thought can extend to thousands of tokens of internal reasoning. It permits Claude to decompose complex problems into steps, consider multiple approaches, verify its own work, and identify errors before presenting a final answer.

    The impact on quality is considerable. On mathematical reasoning benchmarks, extended thinking improves Claude’s accuracy by 15-30 percentage points on the most difficult problems. On coding tasks, it reduces bugs in first-attempt solutions by roughly 40%. On analytical tasks that require multi-step logic, such as financial modelling or legal analysis, the improvements are even more pronounced.

    Extended thinking operates as follows through the API:

    import anthropic
    
    client = anthropic.Anthropic()
    
    response = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=16000,
        thinking={
            "type": "enabled",
            "budget_tokens": 10000  # Allow up to 10K tokens of thinking
        },
        messages=[
            {
                "role": "user",
                "content": "Analyze the time complexity of this algorithm and suggest optimizations..."
            }
        ]
    )
    
    # The response includes both thinking and text blocks
    for block in response.content:
        if block.type == "thinking":
            print(f"Internal reasoning: {block.thinking}")
        elif block.type == "text":
            print(f"Response: {block.text}")

    The budget_tokens parameter controls the volume of “thinking” Claude is permitted. A higher budget yields more thorough reasoning but slower responses and higher costs. Simple questions do not require extended thinking. For complex multi-step problems (debugging a race condition, optimizing a database query, analyzing a complex contract), a generous thinking budget can be the difference between a mediocre answer and an excellent one.

    Caution: Extended thinking tokens are billed at the same rate as output tokens. A 10,000-token thinking budget on Opus 4.6 costs up to $0.75 per request. The feature should be applied strategically rather than on every API call.

    Key Capabilities Across Claude Model Tiers Capability Level 100 80 60 40 20 Coding Reasoning Ext. Thinking Speed Cost Eff. Opus 4.6 Sonnet 4.6 Haiku 4.5

    In Claude Code, extended thinking is invoked automatically when the model encounters complex tasks. No manual configuration is required; the system allocates a thinking budget based on the complexity of the request. This is one reason that Claude Code can autonomously resolve multi-file bugs that simpler tools cannot address.

     

    Tool Use and Function Calling

    Large language models are powerful, but they have fundamental limitations. They cannot check current weather, look up a stock price, query a database, or send an email on their own. Tool use (also called function calling) bridges this gap by allowing Claude to invoke external functions defined by the developer.

    When tool definitions are provided, Claude can decide when to call each tool, what arguments to pass, and how to incorporate the results into its response. This transforms Claude from a text generator into an agent capable of taking actions in external systems.

    A practical example is the provision of stock-price lookups:

    import anthropic
    import json
    
    client = anthropic.Anthropic()
    
    # Define the tools Claude can use
    tools = [
        {
            "name": "get_stock_price",
            "description": "Get the current stock price for a given ticker symbol",
            "input_schema": {
                "type": "object",
                "properties": {
                    "ticker": {
                        "type": "string",
                        "description": "The stock ticker symbol (e.g., AAPL, GOOGL)"
                    }
                },
                "required": ["ticker"]
            }
        }
    ]
    
    response = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=1024,
        tools=tools,
        messages=[
            {"role": "user", "content": "What's the current price of NVIDIA stock?"}
        ]
    )
    
    # Claude will respond with a tool_use block
    for block in response.content:
        if block.type == "tool_use":
            print(f"Claude wants to call: {block.name}")
            print(f"With arguments: {json.dumps(block.input)}")
            # You would execute the function and send the result back

    Tool use is not restricted to simple lookups. Advanced patterns provide Claude with access to a full suite of tools, including database query tools, file-system tools, API-calling tools, and web-search tools, and permit Claude to orchestrate complex multi-step workflows. For example, a developer might ask Claude to “find all customers who signed up last month, check which ones have not made a purchase, and draft a personalized re-engagement email for each.” Claude would use multiple tools in sequence, making decisions at each step based on the data retrieved.

    This is how Claude Code operates internally. When Claude Code is asked to “fix the failing tests,” it uses tools to read files, run shell commands, edit code, and execute tests, with all of these actions orchestrated by the model’s reasoning capabilities.

     

    Model Context Protocol: An Open Standard for AI Integration

    If tool use is the mechanism by which Claude interacts with external systems, the Model Context Protocol (MCP) is the standard that makes those interactions universal and interoperable. Developed by Anthropic and released as an open standard, MCP is among the most important and most underappreciated developments in the AI ecosystem.

    The problem that MCP addresses is straightforward but consequential. Every AI application today must connect to external data sources and tools: databases, file systems, APIs, SaaS applications, development tools, and others. Without a standard protocol, every integration must be custom-built. Integrating Claude with a PostgreSQL database requires a custom tool. Reading from Google Drive requires another. Accessing Jira tickets requires a third. This approach does not scale.

    MCP provides a standardized protocol for AI-to-tool communication. It functions as a USB equivalent for AI integrations. Just as USB allowed any peripheral to be connected to any computer without custom drivers, MCP allows any data source or tool to be connected to any AI model without custom integration code.

    The protocol defines three types of capabilities that an MCP server can offer:

    • Tools: Functions the AI can call (query a database, create a file, send a message)
    • Resources: Data sources the AI can read (documents, database records, API responses)
    • Prompts: Predefined templates for common interactions

    An MCP configuration in Claude Code has the following form:

    // .claude/mcp.json in your project root
    {
      "mcpServers": {
        "postgres": {
          "command": "npx",
          "args": ["-y", "@modelcontextprotocol/server-postgres"],
          "env": {
            "DATABASE_URL": "postgresql://user:pass@localhost/mydb"
          }
        },
        "github": {
          "command": "npx",
          "args": ["-y", "@modelcontextprotocol/server-github"],
          "env": {
            "GITHUB_TOKEN": "ghp_..."
          }
        },
        "filesystem": {
          "command": "npx",
          "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/docs"]
        }
      }
    }

    With this configuration, Claude Code can query a PostgreSQL database directly to understand the schema before writing code, examine GitHub issues and pull requests for context, and read documentation files, without requiring any of this information to be copied into the conversation manually.

    The MCP ecosystem has expanded rapidly. As of early 2026, official and community MCP servers are available for PostgreSQL, MySQL, MongoDB, Redis, GitHub, GitLab, Jira, Confluence, Slack, Google Drive, AWS services, Kubernetes, Docker, and dozens of additional systems. Many organizations are building custom MCP servers for their internal tools and APIs.

    Key Takeaway: MCP is to AI integrations what REST APIs were to web services: a standardized mechanism that allows different systems to communicate. For organizations building AI-powered applications, investing time in understanding and adopting MCP is likely to yield returns as the ecosystem matures.

     

    API and SDK: Building with Claude

    Whether the project is a simple chatbot or a complex multi-agent system, the Anthropic API and its official SDKs serve as the entry point. The API has matured substantially since its early releases, and the developer experience in 2026 is refined and well-documented.

    Python SDK Examples

    The Anthropic Python SDK is the most widely used means of integrating Claude into applications. The following complete example demonstrates the principal features:

    # Install: pip install anthropic
    import anthropic
    
    client = anthropic.Anthropic()  # Reads ANTHROPIC_API_KEY from environment
    
    # Basic message
    response = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=1024,
        messages=[
            {"role": "user", "content": "Explain quantum computing in simple terms."}
        ]
    )
    print(response.content[0].text)
    
    # System prompt + conversation history
    response = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=2048,
        system="You are a senior Python developer. Be concise and include code examples.",
        messages=[
            {"role": "user", "content": "How do I implement a binary search tree?"},
            {"role": "assistant", "content": "Here's a clean BST implementation..."},
            {"role": "user", "content": "Now add a method to find the k-th smallest element."}
        ]
    )
    
    # Streaming for real-time responses
    with client.messages.stream(
        model="claude-sonnet-4-6",
        max_tokens=4096,
        messages=[
            {"role": "user", "content": "Write a comprehensive guide to Python decorators."}
        ]
    ) as stream:
        for text in stream.text_stream:
            print(text, end="", flush=True)

    The TypeScript/JavaScript SDK follows a near-identical structure:

    // Install: npm install @anthropic-ai/sdk
    import Anthropic from "@anthropic-ai/sdk";
    
    const client = new Anthropic();
    
    const response = await client.messages.create({
      model: "claude-sonnet-4-6",
      max_tokens: 1024,
      messages: [
        { role: "user", content: "Explain the JavaScript event loop." }
      ]
    });
    
    console.log(response.content[0].text);

    Both SDKs support all Claude features: tool use, extended thinking, streaming, image and PDF input, system prompts, and batch processing.

    Pricing Comparison

    Understanding pricing is important for organizations building production applications. The following table compares Claude pricing with that of the principal competitors:

    Model Provider Input (per M tokens) Output (per M tokens) Context Window
    Claude Opus 4.6 Anthropic $15.00 $75.00 200K (up to 1M)
    Claude Sonnet 4.6 Anthropic $3.00 $15.00 200K
    Claude Haiku 4.5 Anthropic $0.80 $4.00 200K
    GPT-4o OpenAI $2.50 $10.00 128K
    GPT-4.5 OpenAI $75.00 $150.00 128K
    Gemini 2.5 Pro Google $1.25 $10.00 1M
    Gemini 2.5 Flash Google $0.15 $0.60 1M
    Llama 4 Maverick Meta (open source) Free (self-host) / varies Free (self-host) / varies 1M
    DeepSeek V3 DeepSeek $0.27 $1.10 128K

     

    Key Takeaway: Claude Sonnet 4.6 offers the most favourable quality-to-price ratio for most use cases. GPT-4o is slightly less expensive for input tokens but has a smaller context window. Gemini 2.5 Flash and DeepSeek V3 are the budget options, although they trail substantially in reasoning quality. For maximum capability, Opus 4.6 and GPT-4.5 are the premium choices, with Opus generally offering stronger coding and reasoning performance at less than half the price.

     

    Safety and Alignment: Anthropic’s Approach

    Anthropic was founded specifically to build safe AI. This statement is not a marketing tagline but the organization’s core mission, and it shapes every aspect of how Claude is developed and deployed. Understanding Anthropic’s safety approach is important because it directly affects how Claude behaves, what it will and will not do, and why it sometimes differs in character from competing models.

    Constitutional AI (CAI) is Anthropic’s foundational alignment technique. Rather than relying solely on human feedback to train the model (the RLHF approach used by OpenAI and others), Constitutional AI uses a set of principles, termed a “constitution,” to guide the model’s behaviour. During training, Claude evaluates its own responses against these principles and revises them accordingly. This produces a model that is helpful, harmless, and honest without requiring human labellers to review every training example.

    The practical effect is that Claude is more careful and nuanced than some competitors in sensitive areas. It declines clearly harmful requests, but it also engages thoughtfully with complex ethical questions rather than refusing them outright. Anthropic has worked specifically to avoid the “alignment tax”, the perception that safer models are less useful. Claude is designed to be both safer and more capable.

    Responsible Scaling Policy (RSP) is Anthropic’s framework for deciding when and how to deploy more powerful models. The RSP defines “AI Safety Levels” (ASL), analogous to biosafety levels, that specify the safety evaluations and security measures required before a model of a given capability level can be deployed. As models become more capable, they must pass increasingly rigorous safety evaluations.

    This matters for users and developers because Claude’s capabilities are not only technically constrained but also institutionally constrained. Anthropic will not release a model that passes dangerous capability thresholds without corresponding safety measures, even if competitors release less rigorously tested models first.

    What this means in practice:

    • Claude will not help create malware, generate CSAM, or assist with weapons development
    • Claude will engage with nuanced topics (politics, ethics, sensitive history) thoughtfully rather than refusing outright
    • Claude will acknowledge uncertainty rather than fabricating information
    • Claude will follow system prompts from developers while maintaining core safety boundaries
    • Enterprise customers get additional controls for content filtering and usage policies
    Tip: Developers building customer-facing applications with Claude should review Anthropic’s system prompt documentation carefully. A well-constructed system prompt provides substantial control over Claude’s tone, behaviour, and boundaries within the safety constraints.

     

    Real-World Applications: How Teams Are Using Claude

    Benchmarks and feature lists indicate what a model can do in theory. Real-world deployments show what it does in practice. The following sections describe how companies and developers are using Claude across domains in 2026.

    Software Development. This is Claude’s strongest domain. Companies ranging from startups to Fortune 500 enterprises use Claude Code as part of their development workflow. GitLab has reported that teams using Claude Code experienced a 40% reduction in time-to-merge for pull requests. Replit integrated Claude as its primary AI backend, supporting code generation for millions of users. Individual developers report that Claude Code handles approximately 60-80% of routine coding tasks (writing boilerplate, implementing standard patterns, writing tests, fixing bugs), allowing them to focus on architecture and design decisions.

    Research and Analysis. Academic researchers use Claude to synthesize literature, analyze datasets, and draft papers. Investment analysts use it to process earnings calls, SEC filings, and market data. Legal professionals use it to review contracts and identify relevant precedents. The principal advantage Claude offers in these settings is its large context window, which allows the ingestion of hundreds of pages of source material within a single conversation.

    Content Creation. Marketing teams use Claude to draft blog posts, social-media content, email campaigns, and product documentation. Unlike earlier AI writing tools that produced generic, stilted prose, Claude’s output is conversational, well-structured, and adaptable to different tones and audiences. Many content teams use Claude as a first-draft generator and then edit and refine the output rather than writing from scratch.

    Customer Service. Companies deploy Claude-powered chatbots that handle customer inquiries with substantially more nuance than traditional rule-based systems. Claude understands context, handles follow-up questions, escalates appropriately, and maintains a consistent brand voice. Anthropic offers enterprise features specifically for this use case, including content filtering, usage analytics, and integration with existing customer-service platforms.

    Data Engineering and Analytics. Claude performs well at writing SQL queries, building data pipelines, creating visualizations, and explaining complex datasets. Data analysts who find Python or SQL challenging can describe their requirements in natural language and obtain working code. When combined with MCP servers that connect directly to databases, Claude can query, analyze, and summarize data end-to-end.

    Education. Teachers use Claude to create lesson plans, generate practice problems, and develop assessment rubrics. Students use it as a tutor that can explain concepts, work through problems step by step, and adapt to their level of understanding. Anthropic has partnered with several educational institutions to develop AI literacy programmes that teach students how to use AI tools effectively and critically.

     

    Claude Compared with GPT-4o, Gemini 2.5, and Other Models

    The AI landscape in early 2026 is the most competitive it has been. Four major participants (Anthropic, OpenAI, Google, and Meta), together with strong challengers such as DeepSeek, are advancing the frontier. The following section provides a measured assessment of Claude’s position relative to the competition.

    Capability Claude (Opus 4.6) GPT-4o Gemini 2.5 Pro Llama 4 Maverick DeepSeek V3
    Coding Excellent Very Good Very Good Good Very Good
    Reasoning Excellent Very Good Excellent Good Good
    Long Context Very Good (200K-1M) Good (128K) Excellent (1M) Excellent (1M) Good (128K)
    Multimodal Good (images, PDFs) Excellent (images, audio, video) Excellent (images, audio, video) Good (images) Good (images)
    Instruction Following Excellent Very Good Good Fair Good
    Safety Industry Leading Very Good Good Variable Fair
    Price/Performance Very Good (Sonnet tier) Very Good Excellent (Flash tier) Excellent (open source) Excellent
    Open Source No No No Yes Yes

     

    Claude and GPT-4o (OpenAI). This is the comparison most readers consider central. GPT-4o remains a strong all-around model with substantial multimodal capabilities; it can process images, audio, and video natively, whereas Claude is currently limited to images and PDFs. GPT-4o also benefits from the substantial ChatGPT user base and ecosystem. However, Claude consistently outperforms GPT-4o on coding benchmarks (SWE-bench, HumanEval+), complex reasoning tasks (GPQA), and instruction following. Claude’s larger context window (200K versus 128K) is a meaningful advantage in document-heavy workflows. OpenAI’s GPT-4.5 narrows the reasoning gap but at substantially higher cost.

    Claude and Gemini 2.5 Pro (Google). Gemini’s principal advantage is its native 1-million-token context window and its deep integration with Google’s ecosystem (Search, Workspace, Cloud). For tasks that require processing very large volumes of data in a single pass, Gemini is difficult to surpass. Google also offers Gemini 2.5 Flash at aggressive pricing, making it attractive for cost-sensitive applications. On pure reasoning and coding quality, however, Claude Opus and Sonnet retain an advantage. Gemini also tends to be less reliable at following complex multi-step instructions.

    Claude and Llama 4 (Meta). Llama 4 represents a substantial advance for open-source AI. The Maverick variant, a mixture-of-experts model, offers strong performance at a fraction of the cost when self-hosted. For organizations with capable ML infrastructure teams and strict data-residency requirements, Llama is compelling. However, Llama models generally trail the closed-source leaders on the most demanding reasoning and coding tasks, and operating them requires considerable infrastructure investment.

    Claude and DeepSeek V3. DeepSeek has been the surprise development of 2025-2026. The V3 model offers performance close to GPT-4o at a fraction of the cost, and it has been released as open source. DeepSeek is particularly popular in price-sensitive markets and for developers who wish to self-host. The trade-offs are weaker instruction following, less reliable safety guardrails, and substantially less capability on the most difficult reasoning tasks compared to Claude or GPT-4o.

    Caution: AI benchmarks change rapidly. The specific figures cited here may have shifted by the time of reading. The structural differences (Anthropic’s safety focus, Google’s ecosystem integration, Meta’s open-source approach, DeepSeek’s cost efficiency) are more durable than any particular benchmark score.

     

    Conclusion

    The Claude ecosystem in 2026 represents not merely incremental improvement but the maturation of AI from a novelty into genuine infrastructure. The three-tier model family provides developers with precise control over the capability-cost-speed trade-off. Claude Code transforms how software is built by offering genuine agentic coding rather than enhanced autocomplete. Extended thinking delivers measurably improved results on difficult problems. The Model Context Protocol is creating a standardized integration layer that the broader industry is adopting. Anthropic’s sustained focus on safety means that as these models become more capable, they also become more trustworthy.

    For developers, the most consequential action available is to apply Claude Code to a real project rather than a toy example. The experience of providing a natural-language description of a complex task and observing Claude navigate a codebase, write code across multiple files, run tests, and resolve issues autonomously is qualitatively different from previous AI tooling. It does not replace developer skill; it amplifies it.

    For organizations building applications, the Anthropic API with Claude Sonnet 4.6 as the default model offers the most favourable balance of quality, speed, and cost currently available. Extended thinking can be added for difficult problems, tool use for interaction with external systems, and MCP for seamless integration with data sources.

    For those evaluating the competitive landscape, no single “best” AI model exists; there are only trade-offs. Claude leads on coding and reasoning. Gemini leads on context length and ecosystem integration. Llama and DeepSeek lead on cost and openness. GPT-4o leads on multimodal breadth. The appropriate choice depends on the specific use case, budget, and priorities.

    What is clear is that the era of AI as a curiosity has passed. These are substantive tools used by capable teams to build substantive products. Claude, with its considered balance of capability and safety, sits at the centre of that transformation.

    The question is no longer whether to use AI in a workflow but how to use it most effectively. In 2026, Claude provides more avenues for that answer than at any previous point.

     

    References and Further Reading

     

    This article is for informational purposes only and does not constitute investment, financial, or professional advice. AI capabilities, pricing, and benchmarks change frequently, verify current details at the official documentation links above.

  • OpenClaw: The Open-Source Robotic Manipulation Framework Revolutionizing AI Research

    Summary

    What this post covers: A detailed examination of OpenClaw, the open-source framework for robotic manipulation research, including its architecture, supported robot hands, comparison to alternatives, and the reasons it is reshaping how laboratories train dexterous grasping policies.

    Key insights:

    • OpenClaw consolidates simulation, training and sim-to-real transfer into a single MuJoCo-based, Gymnasium-compatible framework. This eliminates the weeks of infrastructural work that every manipulation laboratory previously rebuilt from scratch.
    • Its modular design allows researchers to swap robot models (Allegro, Shadow, LEAP, Franka Panda, Robotiq) and tasks independently. The same grasping experiment can be re-run on three different hands by changing a single configuration line.
    • Compared with Isaac Gym (locked to NVIDIA), PyBullet (lower fidelity) and task-specific repositories such as DexMV and DexPoint, OpenClaw is the only framework that combines high-fidelity contact dynamics, hardware-agnostic execution (CPU, CUDA and Apple Silicon) and reproducibility by default.
    • The framework’s domain randomisation and system identification tools deliver real-world transfer rates that were previously achievable only by major industrial laboratories operating proprietary stacks.
    • The principal current limitations are GPU memory pressure during large-scale parallel rollouts and a still-young ecosystem of pretrained foundation-model checkpoints. Both are explicit targets on the roadmap.

    Main topics: What Is OpenClaw?, Origins and Mission: Democratizing Robotic Manipulation Research, Technical Architecture: Under the Hood, How OpenClaw Compares to Other Robotics Frameworks, Getting Started with OpenClaw, Real-World Applications, Community and Ecosystem, Future Directions: What Comes Next, The Broader Impact on Embodied AI, Challenges and Limitations, Final Thoughts, References.

    In early 2025, a research team at Stanford demonstrated a robotic hand folding a t-shirt in under thirty seconds. The robot did not rely on a million-dollar proprietary system. It ran on an open-source framework that any graduate student could download, modify and deploy. That framework was OpenClaw, and within months of its public release it had become one of the fastest-growing repositories in the robotics AI space. The question is no longer whether robots will learn to manipulate objects with human-like dexterity, but how quickly open-source tools will accelerate that trajectory.

    Robotic manipulation, defined as the ability of a machine to grasp, move, rotate and precisely handle physical objects, has long been regarded as one of the most difficult unsolved problems in artificial intelligence. While large language models came to dominate text and diffusion models mastered image generation, enabling a robot to pick up a coffee mug reliably has remained stubbornly difficult. The challenge is not perception or planning alone, but the intricate coordination of fingers, force control and real-time adaptation to an unpredictable physical environment.

    OpenClaw addresses this problem directly. It provides a unified, modular, open-source platform for training robotic manipulation policies, from simple parallel-jaw grippers to complex multi-fingered dexterous hands. It does so in a manner that is accessible, reproducible and designed for the era of foundation models in robotics.

    This article presents a detailed examination of OpenClaw: what it is, how it operates, how it compares with alternatives, and why it matters for the future of embodied AI.

    What Is OpenClaw?

    OpenClaw is an open-source framework for robotic manipulation research, with a particular emphasis on dexterous grasping and in-hand manipulation. It functions as a comprehensive toolkit, providing researchers and engineers with the components required to train, evaluate and deploy robotic manipulation policies, from simulation through to real hardware.

    OpenClaw provides the following.

    • High-fidelity simulation environments for a variety of robotic hands and grippers.
    • Pre-built task suites covering grasping, reorientation, tool use and assembly.
    • Policy learning pipelines integrated with widely used reinforcement learning (RL) libraries.
    • Sim-to-real transfer tools, including domain randomisation and system identification.
    • Benchmarking infrastructure for fair comparison across methods and hardware.
    • A modular architecture that allows robot models, tasks and learning algorithms to be exchanged independently.
    Key Takeaway: OpenClaw is neither solely a simulator nor solely a training framework. It is an end-to-end platform covering the complete pipeline, from task definition to real-world deployment, and is specifically optimised for manipulation and dexterous grasping.

    The framework is built on top of MuJoCo, itself now open source thanks to DeepMind, and provides a Gymnasium-compatible API. This allows it to plug directly into the broader Python RL ecosystem. A practitioner who has trained an agent with Stable Baselines3 or CleanRL already understands the interface.

    OpenClaw supports multiple robot hand models by default, including the Allegro Hand, Shadow Dexterous Hand and LEAP Hand, alongside several parallel-jaw grippers such as the Franka Panda and the Robotiq 2F-85. This multi-platform support is a deliberate design choice: the team behind OpenClaw considers that manipulation research should not be tied to a single hardware vendor.

    Origins and Mission: Democratizing Robotic Manipulation Research

    OpenClaw emerged from a collaboration between researchers at Stanford’s IRIS Lab, UC Berkeley’s AUTOLAB, and several contributors from the broader robotics community. The project arose from a recurring frustration: each laboratory had constructed its own simulation stack, its own training pipeline and its own evaluation protocols. The result was a fragmented landscape in which comparing methods was nearly impossible, and new researchers faced weeks of setup before they could conduct their first experiment.

    The initial release appeared on GitHub in mid-2025, accompanied by a technical report on arXiv. The stated mission was explicit: to provide a unified, reproducible and extensible platform for robotic manipulation research that lowers the barrier to entry while raising the standard for rigour.

    The Problem It Solves

    Before OpenClaw, training a dexterous manipulation policy required choosing among several options, none of which were entirely satisfactory.

    • NVIDIA Isaac Gym and Isaac Lab: powerful GPU-accelerated simulation, but tightly coupled to NVIDIA hardware and a specific workflow. The learning curve is steep and the codebase is large.
    • MuJoCo with custom wrappers: flexible and accurate, but each component (environments, reward functions, training loops and evaluation metrics) had to be built from scratch.
    • PyBullet: straightforward to use but lacking simulation fidelity, particularly for contact-rich manipulation tasks.
    • DexMV, DexPoint and other in-hand manipulation repositories: task-specific repositories that solve one problem but are not designed for reuse or extension.

    OpenClaw consolidates the strongest ideas from these approaches into a single, well-documented framework. It uses MuJoCo for physics simulation, widely regarded as the standard for contact dynamics, wraps the entire system in a clean Gymnasium API, and provides the scaffolding that researchers previously had to construct themselves.

    Design Principles

    The OpenClaw team has been explicit regarding its design philosophy.

    • Modularity over monoliths: every component (robot, task, reward, observation, policy) is a swappable module. The same grasping task can be tested with three different robot hands by changing a single configuration line.
    • Reproducibility by default: fixed random seeds, versioned environments and standardised evaluation protocols are built in rather than added later.
    • Hardware-agnostic operation: the framework runs on CPUs, NVIDIA GPUs and Apple Silicon, without vendor lock-in.
    • Community-driven development: the project uses an open governance model with regular community calls, a contribution guide and a public roadmap.
    Tip: Graduate students and independent researchers starting a new manipulation project may save weeks of setup time by adopting OpenClaw. The pre-built environments and training pipelines allow attention to remain on the research question rather than the infrastructure.

    Technical Architecture: Internal Design

    Understanding OpenClaw’s architecture is essential for any practitioner who wishes to use it effectively or contribute to its development. The framework is organised into several well-defined layers, each with a clearly delimited responsibility.

    The Simulation Layer

    At the foundation sits MuJoCo, Google DeepMind’s physics engine, which has become the de facto standard for robotics simulation. OpenClaw uses MuJoCo for rigid body dynamics, contact simulation, tendon actuation and sensor modelling. The choice of MuJoCo was deliberate: its contact model is arguably the most realistic available for the small-scale, high-force-density interactions that characterise dexterous manipulation.

    OpenClaw wraps MuJoCo with a scene management layer that handles the following.

    • Loading and configuring robot MJCF/URDF models
    • Spawning and randomizing objects (shape, size, mass, friction)
    • Managing camera views for visual observation
    • Applying domain randomization for sim-to-real transfer
    # OpenClaw scene configuration example
    scene_config = {
        "robot": "allegro_hand",
        "object_set": "ycb_subset",
        "table_height": 0.75,
        "camera_views": ["front", "wrist", "overhead"],
        "domain_randomization": {
            "object_mass": {"range": [0.8, 1.2], "type": "multiplicative"},
            "friction": {"range": [0.6, 1.4], "type": "multiplicative"},
            "lighting": {"range": [0.5, 1.5], "type": "uniform"},
        }
    }

    The Environment Layer

    Above the simulation sits the environment layer, which implements the Gymnasium (formerly OpenAI Gym) interface. Each environment defines a specific manipulation task, with the following components.

    • Observation space: Joint positions, velocities, tactile readings, object pose, and optionally visual observations (RGB, depth)
    • Action space: Joint position targets, velocity targets, or torque commands depending on the control mode
    • Reward function: Shaped rewards for task progress, sparse rewards for completion, and optional auxiliary rewards
    • Termination conditions: Success, failure (object dropped), or timeout

    OpenClaw ships with over 30 pre-built environments organized into task categories:

    Task Category Example Tasks Difficulty
    Grasping Power grasp, precision grasp, adaptive grasp Beginner
    Pick and Place Single object, cluttered bin, stacking Intermediate
    In-Hand Manipulation Object reorientation, pen spinning, valve turning Advanced
    Tool Use Screwdriver, hammer, spatula Advanced
    Assembly Peg insertion, gear meshing, cable routing Expert

     

    Reward Shaping and Curriculum Learning

    One of OpenClaw’s strongest features is its reward shaping infrastructure. Manipulation tasks are notoriously difficult to learn from sparse rewards alone, since instructing a robot that “+1 is awarded when the object is in the target pose” produces essentially random exploration that rarely discovers the reward signal.

    OpenClaw addresses this through a composable reward system.

    # OpenClaw composable reward example
    reward_config = {
        "components": [
            {
                "type": "distance_to_object",
                "weight": 0.3,
                "params": {"threshold": 0.05, "temperature": 10.0}
            },
            {
                "type": "grasp_stability",
                "weight": 0.3,
                "params": {"min_contact_force": 0.1, "max_contact_force": 20.0}
            },
            {
                "type": "object_at_target",
                "weight": 0.4,
                "params": {"position_threshold": 0.02, "orientation_threshold": 0.1}
            }
        ],
        "success_bonus": 10.0,
        "drop_penalty": -5.0
    }

    Each reward component is a standalone module that may be combined as needed. The framework also supports automatic curriculum learning, in which task difficulty increases gradually as the agent improves. An in-hand reorientation task, for example, may begin with small target rotations of 30 degrees and progressively advance to full 180-degree flips.

    Policy Learning Integration

    OpenClaw does not duplicate effort in the area of policy learning. Instead, it provides clean integrations with the most widely used RL libraries in the Python ecosystem.

    RL Library Integration Level Supported Algorithms
    Stable Baselines3 Full (native wrappers) PPO, SAC, TD3, HER
    CleanRL Full (example scripts) PPO, SAC, DQN
    rl_games Full (GPU-accelerated) PPO (asymmetric actor-critic)
    SKRL Community-maintained PPO, SAC, RPO
    Custom PyTorch Via Gymnasium API Any

     

    The integration with Stable Baselines3 is particularly smooth. Because OpenClaw environments implement the standard Gymnasium interface, a policy can be trained in only a few lines of code, as the Getting Started section demonstrates.

    For researchers requiring maximum throughput, OpenClaw also supports vectorised environments via MuJoCo’s native batched simulation. This permits the parallel execution of thousands of environment instances on a single GPU, substantially reducing training time for complex tasks.

    OpenClaw: Reinforcement Learning Loop Observation joints · tactile · pose obs Neural Policy PPO / SAC / TD3 MLP · Transformer action Environment MuJoCo Physics contact · dynamics reward Reward shaped + sparse next observation—policy update loop

    Sim-to-Real Transfer Pipeline

    Simulation is only useful if the policies it produces function on real robots. OpenClaw treats sim-to-real transfer as a first-class concern and provides a structured pipeline that includes the following elements.

    • Domain randomization: Systematic variation of physics parameters (friction, damping, mass), visual properties (textures, lighting, camera noise), and actuation parameters (motor delay, backlash) during training
    • System identification: Tools for measuring real robot parameters and calibrating the simulation to match
    • Observation filtering: Low-pass filtering and noise injection to match real sensor characteristics
    • Action smoothing: Configurable action interpolation to produce smoother, hardware-safe motions
    • ROS 2 integration: A ROS 2 node that wraps trained policies for deployment on real hardware
    Key Takeaway: The sim-to-real pipeline is not an afterthought in OpenClaw. It is a first-class component with dedicated modules for domain randomisation, system identification and hardware deployment. This represents a significant advantage over frameworks that focus exclusively on simulation.

    The ROS 2 integration warrants particular attention. Many academic frameworks leave real-robot deployment as an exercise for the reader. OpenClaw provides a fully functional ROS 2 package (openclaw_ros2) that handles action publishing, observation subscribing, safety limits and emergency stops. For robots that run ROS 2, deployment is genuinely straightforward.

    OpenClaw: Sim-to-Real Transfer MuJoCo Simulation Domain Randomization Contact Dynamics Sensor Noise Injection Mass / Friction Variation Policy Network PPO Training Sys-ID Calibration Action Smoothing Real Robot Allegro / Shadow / LEAP ROS 2 Integration Safety Limits Emergency Stop train randomize deploy fine-tune Dashed arrow = optional real-world fine-tuning after sim deployment

    How OpenClaw Compares to Other Robotics Frameworks

    The robotics simulation landscape in 2026 is crowded. Understanding the position OpenClaw occupies, and the positions it does not, is important for selecting the appropriate tool for a given project.

    Feature OpenClaw Isaac Lab MuJoCo (raw) PyBullet SAPIEN
    Physics Engine MuJoCo PhysX 5 MuJoCo Bullet PhysX 5
    Contact Fidelity Excellent Very Good Excellent Fair Very Good
    GPU Acceleration MuJoCo XLA Native CUDA MuJoCo XLA CPU only Partial
    Dexterous Hand Support 5+ models 2-3 models DIY Limited 2-3 models
    Pre-built Tasks 30+ 20+ None 10+ 15+
    RL Integration SB3, CleanRL, rl_games rl_games, RSL_RL DIY SB3 SB3, custom
    Sim-to-Real Tools Built-in pipeline Domain rand only None None Partial
    ROS 2 Support Native package Planned None Community None
    License Apache 2.0 NVIDIA EULA Apache 2.0 zlib Apache 2.0

     

    OpenClaw vs. Isaac Lab

    NVIDIA’s Isaac Lab, the successor to Isaac Gym, is OpenClaw’s most direct competitor. Isaac Lab has a clear advantage in raw simulation throughput. Its close CUDA integration permits tens of thousands of environments to run simultaneously on a single GPU. For locomotion tasks and large-scale policy search, Isaac Lab is difficult to surpass.

    OpenClaw nonetheless has several advantages specific to manipulation research.

    • Contact physics: MuJoCo’s contact model is generally regarded as more accurate than PhysX for the delicate, high-force-ratio contacts that occur during grasping. This matters when sim-to-real transfer for manipulation is the goal.
    • Licensing: OpenClaw is released under Apache 2.0. Isaac Lab requires acceptance of NVIDIA’s EULA, which can complicate academic publication and redistribution.
    • Accessibility: OpenClaw runs on any hardware, including laptops without NVIDIA GPUs. Isaac Lab requires NVIDIA GPUs.
    • Focus: OpenClaw is purpose-built for manipulation. Isaac Lab is a general-purpose framework that also supports manipulation, but its task library and tooling reflect a broader scope.

    OpenClaw vs. Raw MuJoCo

    Some researchers prefer to work directly with MuJoCo, writing custom environments from scratch. This approach offers maximum flexibility but imposes a substantial development cost. OpenClaw sits on top of MuJoCo, providing the same physics fidelity together with pre-built environments, standardised interfaces and community-maintained robot models. A practitioner may always drop down to raw MuJoCo when necessary, since OpenClaw does not conceal the underlying engine.

    OpenClaw vs. RoboCasa

    RoboCasa, another recent open-source project, focuses on household robot simulation, with an emphasis on mobile manipulation in kitchen and living room environments. It is built on robosuite and MuJoCo and targets a different use case from OpenClaw. RoboCasa excels at large-scale scene-level tasks such as loading a dishwasher or organising a pantry, while OpenClaw excels at fine-grained manipulation tasks such as rotating a screw or inserting a cable. The two are complementary rather than competing, and some researchers use both.

    Tip: The most appropriate framework depends on the specific research question. For dexterous manipulation and sim-to-real transfer, OpenClaw is difficult to surpass. For substantial parallelism in locomotion or large-scale RL, Isaac Lab is preferable. For studies of household mobile manipulation, RoboCasa is the appropriate option.

    Getting Started with OpenClaw

    One of OpenClaw’s design goals is to minimise the time to first experiment. The procedure for moving from zero to training a grasping policy in minutes is described below.

    Installation

    OpenClaw requires Python 3.9 or later and has minimal system dependencies. The recommended installation method uses pip or uv.

    # Using pip
    pip install openclaw
    
    # Or using uv (faster)
    uv pip install openclaw
    
    # For development (includes all extras)
    git clone https://github.com/openclaw-robotics/openclaw.git
    cd openclaw
    uv pip install -e ".[dev,ros2]"

    The base installation pulls in MuJoCo, Gymnasium, NumPy and several other lightweight dependencies. The RL library integrations (Stable Baselines3, CleanRL) are optional extras that may be installed as required.

    # Install with Stable Baselines3 support
    pip install "openclaw[sb3]"
    
    # Install with CleanRL support
    pip install "openclaw[cleanrl]"
    
    # Install with visualization tools
    pip install "openclaw[viz]"

    A First Environment

    The following example creates an environment and interacts with it through the standard Gymnasium interface.

    import gymnasium as gym
    import openclaw  # registers environments
    
    # Create a simple grasping environment
    env = gym.make("OpenClaw-AllegroGrasp-v1", render_mode="human")
    
    # Reset and inspect the spaces
    obs, info = env.reset()
    print(f"Observation shape: {obs.shape}")
    print(f"Action shape: {env.action_space.shape}")
    
    # Run a random policy
    for _ in range(1000):
        action = env.action_space.sample()
        obs, reward, terminated, truncated, info = env.step(action)
        if terminated or truncated:
            obs, info = env.reset()
    
    env.close()

    This creates an environment in which the Allegro Hand must grasp a randomly placed object. The observation includes joint positions, velocities, tactile sensor readings and the object’s pose. The action space comprises the target joint positions for the hand’s 16 actuated degrees of freedom.

    Training a Policy with Stable Baselines3

    Training a grasping policy with PPO requires only a few additional lines.

    import gymnasium as gym
    import openclaw
    from stable_baselines3 import PPO
    from stable_baselines3.common.vec_env import SubprocVecEnv
    from openclaw.wrappers import OpenClawSB3Wrapper
    
    # Create vectorized environments for parallel training
    def make_env(seed):
        def _init():
            env = gym.make("OpenClaw-AllegroGrasp-v1")
            env = OpenClawSB3Wrapper(env)
            env.reset(seed=seed)
            return env
        return _init
    
    # 8 parallel environments
    env = SubprocVecEnv([make_env(i) for i in range(8)])
    
    # Train with PPO
    model = PPO(
        "MlpPolicy",
        env,
        learning_rate=3e-4,
        n_steps=2048,
        batch_size=256,
        n_epochs=10,
        gamma=0.99,
        verbose=1,
        tensorboard_log="./logs/allegro_grasp/"
    )
    
    model.learn(total_timesteps=5_000_000)
    model.save("allegro_grasp_ppo")

    On a modern desktop with eight CPU cores, this configuration trains a competent grasping policy in approximately two to four hours. With GPU-accelerated MuJoCo via MuJoCo XLA, the same training run can complete in under an hour.

    OpenClaw: Training Pipeline Dataset Collection YCB objects · demo data Policy Training PPO · SAC · curriculum Sim Evaluation benchmarks · metrics Real-World Deployment ROS 2 · hardware 1 2 3 4 iterate if eval fails

    Evaluating and Visualizing

    OpenClaw includes built-in evaluation tools that compute standard manipulation metrics:

    from openclaw.evaluation import evaluate_policy, MetricSuite
    
    # Load the trained model
    model = PPO.load("allegro_grasp_ppo")
    
    # Evaluate over 100 episodes
    metrics = evaluate_policy(
        model,
        env_id="OpenClaw-AllegroGrasp-v1",
        n_episodes=100,
        metrics=MetricSuite.GRASPING,  # success rate, grasp time, stability
        render=False,
        seed=42
    )
    
    print(f"Success rate: {metrics['success_rate']:.1%}")
    print(f"Mean grasp time: {metrics['mean_grasp_time']:.2f}s")
    print(f"Grasp stability: {metrics['stability_score']:.2f}")
    
    # Generate a video of the best episode
    from openclaw.visualization import render_episode
    render_episode(model, "OpenClaw-AllegroGrasp-v1", output="grasp_demo.mp4")
    Caution: Training manipulation policies is computationally intensive. Although OpenClaw can run on a laptop for prototyping and debugging, serious training runs benefit substantially from a multi-core CPU or a GPU with MuJoCo XLA support. A budget of at least four to eight hours should be allocated for training a dexterous manipulation policy on standard hardware.

    The Configuration System

    OpenClaw uses YAML configuration files to define experiments, which simplifies tracking and reproducibility.

    # config/experiments/allegro_reorientation.yaml
    environment:
      id: OpenClaw-AllegroReorient-v1
      robot: allegro_hand
      object: cube
      reward:
        type: composable
        components:
          - type: orientation_error
            weight: 0.7
          - type: angular_velocity_penalty
            weight: 0.1
          - type: action_smoothness
            weight: 0.2
        success_bonus: 10.0
    
    training:
      algorithm: ppo
      library: stable_baselines3
      hyperparameters:
        learning_rate: 3e-4
        n_steps: 4096
        batch_size: 512
        n_epochs: 5
        clip_range: 0.2
      total_timesteps: 10_000_000
      n_envs: 16
      seed: 42
    
    domain_randomization:
      enabled: true
      object_mass: [0.7, 1.3]
      friction: [0.5, 1.5]
      motor_strength: [0.9, 1.1]
    
    evaluation:
      n_episodes: 200
      metrics: [success_rate, orientation_error, episode_length]

    The experiment can then be executed with a single command.

    # Train from config
    openclaw train --config config/experiments/allegro_reorientation.yaml
    
    # Evaluate a trained checkpoint
    openclaw eval --config config/experiments/allegro_reorientation.yaml --checkpoint runs/latest/best_model.zip

    Real-World Applications

    Although OpenClaw is fundamentally a research tool, the applications it enables are already entering real-world use. The principal domains in which OpenClaw-trained policies are being tested or deployed are outlined below.

    Warehouse Automation and Logistics

    The growth of e-commerce has created substantial demand for robotic picking and packing systems. Current warehouse robots, including those from Berkshire Grey and Covariant, can handle many objects but struggle with deformable items such as snack packets or clothing, and with densely packed bins. OpenClaw’s emphasis on dexterous grasping makes it a natural fit for training policies that can handle these more demanding cases.

    Several logistics companies have reported using OpenClaw to prototype and pre-train grasping policies in simulation before fine-tuning on their proprietary hardware. The ability to iterate rapidly on reward functions and domain randomisation strategies without occupying expensive robot time is a significant advantage.

    Manufacturing and Assembly

    Precision assembly tasks, including the insertion of connectors, the threading of screws and the alignment of components, demand exactly the kind of contact-rich manipulation in which OpenClaw specialises. Traditional industrial robots address these tasks through rigid programming that moves to exact coordinates and applies precise force, but the approach is brittle and requires extensive calibration for every new part.

    OpenClaw-trained policies can learn adaptive assembly strategies that generalise across part variations. A policy trained to insert a USB connector, for example, can learn to use the tactile feedback from the initial contact to adjust its insertion angle, a behaviour that is difficult to program manually but emerges naturally from RL training with appropriate reward shaping.

    Surgical Robotics

    Surgical robots such as the da Vinci system require highly precise manipulation within constrained spaces. While OpenClaw is not used directly in clinical systems (medical device regulation constitutes a separate set of challenges), it is being applied in research laboratories to develop and evaluate manipulation policies for surgical tasks. The fine-grained contact modelling provided by MuJoCo is essential here, since surgical tasks involve forces in the millinewton range and position accuracy in fractions of a millimetre.

    Research groups have used OpenClaw to train policies for suturing, tissue retraction and needle insertion, publishing results that demonstrate performance competitive with hand-engineered controllers at a fraction of the development time.

    Household Robotics

    The long-standing objective of a general-purpose household robot, capable of cooking, cleaning, doing laundry and organising the home, requires mastery of a wide variety of manipulation tasks. OpenClaw’s modular design supports the training of specialist policies for distinct manipulation primitives such as grasping, pouring, wiping and folding, which can then be composed into higher-level behaviours.

    This is particularly relevant as companies such as Figure, 1X and Sanctuary AI work toward general-purpose humanoid robots. Such robots require thousands of manipulation skills, and training each one from scratch on real hardware is impractical. OpenClaw provides the simulation infrastructure necessary to develop these skills at scale.

    Key Takeaway: OpenClaw is not merely an academic exercise. The framework is already being used to develop manipulation policies for warehouse logistics, manufacturing, surgical robotics and household robots. Its emphasis on sim-to-real transfer makes it practically relevant rather than only theoretically interesting.

    Community and Ecosystem

    An open-source project depends on its community for survival. OpenClaw’s growth since its mid-2025 release has been notable, particularly by robotics standards, in which project adoption tends to be slower than in web development or natural language processing.

    GitHub Activity

    As of early 2026, the OpenClaw repository shows healthy community engagement, as summarised below.

    Metric Value
    GitHub Stars ~4,200
    Forks ~680
    Contributors 85+
    Open Issues ~120
    Merged PRs (last 3 months) ~190
    PyPI Monthly Downloads ~15,000

     

    These figures are significant for a robotics framework. By comparison, robosuite, one of the more established manipulation frameworks, has around 1,500 stars and grew considerably more slowly in its first year. OpenClaw’s rapid adoption reflects both the quality of the software and the unmet need it addresses within the community.

    Research Papers and Publications

    A key indicator of a research framework’s value is the volume of papers that adopt it. In the months following its release, OpenClaw has appeared in preprints and submissions to major robotics conferences including CoRL, ICRA and RSS. The most common use cases in published work are as follows.

    • Benchmarking new RL algorithms on standard manipulation tasks.
    • Evaluating sim-to-real transfer methods.
    • Developing new reward shaping and curriculum learning approaches.
    • Training foundation models for manipulation, using OpenClaw’s diverse task suite as training data.

    The framework’s standardised evaluation protocol has been particularly valuable to the research community. Before OpenClaw, comparing manipulation methods across papers was nearly impossible, since each group used different environments, metrics and evaluation procedures. Papers may now simply report their scores on OpenClaw benchmarks, making like-for-like comparison feasible.

    Ecosystem Integrations

    OpenClaw does not exist in isolation. The team has built or facilitated integrations with several important tools in the robotics ecosystem.

    • Weights & Biases and TensorBoard: built-in logging of training metrics, episode videos and evaluation results.
    • Hugging Face Hub: pre-trained policy checkpoints are available on Hugging Face, permitting download and fine-tuning without training from scratch.
    • LeRobot: integration with Hugging Face’s LeRobot framework for learning from demonstrations.
    • Open X-Embodiment: compatibility with the Open X-Embodiment dataset format for cross-robot transfer learning.
    • URDF and MJCF converters: tools for importing robot models from common formats.

    Future Directions: What Comes Next

    OpenClaw remains a young project, and its roadmap outlines ambitious plans that align with the broader trends in robotics AI research.

    Foundation Models for Dexterous Manipulation

    The principal bet in robotics AI at present is that the scaling laws that produced GPT-4 and Claude can be applied to robot policies. With sufficiently diverse training data, a single model can generalise to new objects, new tasks and even new robot embodiments.

    OpenClaw positions itself as the training ground for these manipulation foundation models. Its diverse task suite, standardised observation format and multi-robot support make it well suited to generating the large-scale, diverse training data that foundation models require. The team has published preliminary results indicating that a single policy trained across all OpenClaw tasks simultaneously achieves approximately 70 percent of the performance of task-specific specialists, a promising starting point.

    Language-Conditioned Manipulation

    Instructing a robot in natural language (“pick up the red mug and place it on the top shelf”) is a natural interface that requires bridging language understanding and physical manipulation. OpenClaw’s forthcoming v2.0 release includes support for language-conditioned tasks, in which the goal is specified as a textual instruction rather than a numeric target pose.

    This integration builds on recent advances in vision-language models (VLMs) and connects manipulation policies to the broader multimodal AI ecosystem. The planned approach uses a pre-trained VLM to encode the language instruction and visual observation into a shared representation, which then conditions the manipulation policy.

    Advanced Tactile Sensing

    Humans rely heavily on touch for manipulation, as anyone who has attempted to thread a needle with numb fingers will appreciate. OpenClaw currently supports basic contact force sensing, but the roadmap includes integration with high-fidelity tactile sensor simulations, including GelSight-style optical tactile sensors and BioTac-style multi-modal sensors.

    This is a technically challenging addition, since tactile simulation requires modelling deformable surfaces at a finer resolution than rigid body dynamics. The team is collaborating with tactile sensing researchers to develop efficient simulation methods that capture the essential physics without prohibitive computational cost.

    Multi-Agent and Bimanual Manipulation

    Many real-world manipulation tasks require two hands, including folding laundry, opening a jar and assembling furniture. OpenClaw’s architecture supports multi-agent environments, and the team is developing a suite of bimanual manipulation tasks that require coordination between two robot arms or hands. This is a particularly active research area, since bimanual manipulation introduces challenges in coordination, shared workspace planning and collaborative learning that do not exist in single-arm settings.

    Deformable Object Manipulation

    Cloth, rope, dough and other deformable objects represent the next frontier in manipulation. These objects have effectively infinite-dimensional state spaces and complex dynamics that are considerably harder to simulate and learn from than rigid objects. OpenClaw’s roadmap includes integration with deformable body simulation, likely through MuJoCo’s expanding support for soft body dynamics or through coupling with specialised deformable object simulators.

    Key Takeaway: OpenClaw’s roadmap, comprising foundation models, language conditioning, advanced tactile sensing, bimanual manipulation and deformable objects, reads as a research agenda for the entire field of robotic manipulation. The framework is not only solving present problems but also building infrastructure for the next generation of challenges.

    The Broader Impact on Embodied AI

    OpenClaw forms part of a larger movement in AI research that is shifting attention from digital intelligence (text, images, code) to physical intelligence (robots that interact with the real world). This shift is driven by the recognition that genuinely general AI must understand and act in the physical world, not only the digital one.

    The analogy with ImageNet is instructive. Before ImageNet, computer vision research was fragmented: each laboratory used its own dataset, evaluation protocol and metrics. ImageNet provided a common benchmark that aligned the community, enabled fair comparison and ultimately accelerated progress by an order of magnitude. OpenClaw aspires to play a similar role for robotic manipulation.

    An equity dimension is also important. Robotics research has historically been expensive: a dexterous robot hand costs between $50,000 and $200,000, and the engineering support required to maintain one is substantial. By providing high-fidelity simulation that runs on commodity hardware, OpenClaw allows researchers without access to expensive equipment to participate in manipulation research. A PhD student in Nairobi or Sao Paulo can now train and evaluate manipulation policies on the same benchmarks as laboratories at Stanford or MIT.

    The connection to industry is similarly important. As companies race to deploy humanoid robots and advanced manipulation systems, demand for trained manipulation policies far outstrips supply. OpenClaw’s growing library of pre-trained policies on Hugging Face Hub is beginning to fill this gap, providing a starting point that companies can fine-tune to their specific hardware and tasks.

    Challenges and Limitations

    No framework is without limitations, and OpenClaw faces several significant challenges that the community is actively addressing.

    Simulation-reality gap. Despite domain randomisation and system identification, sim-trained policies still struggle to transfer perfectly to real hardware. The gap is particularly pronounced for tasks involving soft contact, dynamic manipulation such as throwing or catching, and manipulation of deformable objects. OpenClaw mitigates this difficulty but does not eliminate it.

    Computational cost. Training dexterous manipulation policies remains expensive. A serious experiment on in-hand reorientation can consume hundreds of GPU-hours. While this remains substantially cheaper than real-robot training, it is still a barrier for researchers with limited computational resources.

    Sensor realism. OpenClaw’s tactile and visual sensor models, while functional, do not yet capture the full complexity of real sensors. Real camera images contain noise, motion blur, occlusion and lighting variations that are only partially reproduced in simulation.

    Long-horizon tasks. Most of OpenClaw’s current tasks are relatively short, lasting a few seconds to a minute of robot time. Long-horizon manipulation tasks, such as assembling a piece of furniture or preparing a meal, require hierarchical planning and memory that the current framework does not natively support.

    Caution: OpenClaw is a powerful tool, but it is not a complete solution. Sim-to-real transfer remains an active research challenge, and policies that perform well in simulation may fail on real hardware without careful calibration, domain randomisation and testing. Validation on real hardware should always precede deployment in any safety-critical context.

    Final Thoughts

    OpenClaw represents something that the robotics community has long required: a unified, open-source platform that renders dexterous manipulation research accessible, reproducible and rigorous. By building on the solid foundation of MuJoCo, adopting the standard Gymnasium interface, and providing first-class support for sim-to-real transfer, it has established itself as the framework of choice for a growing portion of the manipulation research community.

    The framework’s rapid adoption, comprising thousands of GitHub stars, dozens of research papers and an active contributor community, suggests it has struck a productive balance between simplicity and capability. It is simple enough that a graduate student can run a first experiment in an afternoon, yet capable enough that leading research laboratories use it for advanced work on manipulation foundation models.

    For researchers, OpenClaw offers a way to concentrate on the science rather than on the infrastructure. For engineers, it provides a pre-validated simulation-to-deployment pipeline. For the broader AI community, it is a reminder that the next frontier of artificial intelligence concerns physical interaction with the real world, not only language and images.

    The robot that folds laundry, assembles furniture or assists in surgery will need to master the craft of manipulation. OpenClaw is helping to build the tools that make this possible, and is doing so in a manner that any researcher or engineer can contribute to and benefit from. In a field often dominated by proprietary systems and closed research, that openness may be its most distinctive feature.

    References

    1. OpenClaw GitHub Repository,https://github.com/openclaw-robotics/openclaw
    2. Todorov, E., Erez, T., & Tassa, Y.—”MuJoCo: A physics engine for model-based control.” IEEE/RSJ International Conference on Intelligent Robots and Systems (IROS), 2012.
    3. Makoviychuk, V., et al.—”Isaac Gym: High Performance GPU-Based Physics Simulation For Robot Learning.” NeurIPS 2021.
    4. Zhu, Y., et al.,”robosuite: A Modular Simulation Framework and Benchmark for Robot Learning.” arXiv:2009.12293.
    5. Rafailov, R., et al.—”D-Grasp: Physically Plausible Dynamic Grasp Synthesis for Hand-Object Interactions.” CVPR 2022.
    6. Chen, T., et al.—”Bi-DexHands: Towards Human-Level Bimanual Dexterous Manipulation.” IEEE Transactions on Pattern Analysis and Machine Intelligence, 2023.
    7. Open X-Embodiment Collaboration,”Open X-Embodiment: Robotic Learning Datasets and RT-X Models.” arXiv:2310.08864.
    8. Cadene, S., et al.—”LeRobot: Democratizing Robotics with End-to-End Learning.” Hugging Face, 2024.
    9. Nasiriany, S., et al.—”RoboCasa: Large-Scale Simulation of Everyday Tasks for Generalist Robots.” arXiv:2406.02523.
    10. Xia, F., et al.,”SAPIEN: A SimulAted Part-based Interactive ENvironment.” CVPR 2020.
    11. Schulman, J., et al.—”Proximal Policy Optimization Algorithms.” arXiv:1707.06347.
    12. Haarnoja, T., et al.—”Soft Actor-Critic: Off-Policy Maximum Entropy Deep Reinforcement Learning with a Stochastic Actor.” ICML 2018.
  • Time-Series Forecasting in 2026: From ARIMA to Foundation Models — A Complete Guide

    Summary

    What this post covers: A practitioner’s roadmap to time-series forecasting in 2026, tracing the evolution from ARIMA through PatchTST and iTransformer to foundation models like TimesFM, Chronos, and Moirai, with benchmarks and a model-selection framework.

    Key insights:

    • Classical methods (ARIMA, ETS, seasonal naive) remain competitive baselines that the M5 and subsequent competitions show often match deep learning on univariate, well-behaved series, so always benchmark against them first.
    • Gradient boosting (LightGBM, XGBoost) quietly dominates many real-world, feature-rich forecasting problems and beat all deep learning entries at the M5 competition; ignore it at your peril.
    • Foundation models like TimesFM, Chronos, and Moirai deliver competitive zero-shot forecasts without any task-specific training and are bridging toward fully-supervised accuracy via efficient fine-tuning on a few hundred examples.
    • PatchTST and iTransformer demonstrate that the right inductive bias (patching the time axis, inverting which dimension attention operates over) often matters more than model size or attention sophistication.
    • The best forecasting system is the best pipeline, not the best model: data quality, proper time-series cross-validation, forecast reconciliation, and monitoring matter more than any single architecture choice.

    Main topics: Why Time-Series Forecasting Matters More Than Ever, Classical Foundations That Still Work, Gradient Boosting for Time Series: An Underused Practitioner Tool, The Deep Learning Era: N-BEATS, N-HiTS, and TFT, PatchTST: When Vision Meets Time Series (ICLR 2023), iTransformer: Inverting the Attention Paradigm (ICLR 2024), Foundation Models: Zero-Shot Forecasting Arrives, Benchmarks: How Models Actually Compare, Practical Model Selection Guide, Implementation: End-to-End Forecasting Pipeline, The Future of Forecasting, References.

    In March 2021, the container ship Ever Given lodged sideways in the Suez Canal, blocking 12% of global trade for six days. The economic damage exceeded 54 billion USD. Supply chain managers across the world were required to re-route shipments, adjust inventory forecasts, and estimate when normal flow would resume. The companies that weathered the crisis best were not those with the largest inventories but those with the most accurate demand forecasting models, capable of recalculating their entire supply chain within hours rather than weeks.

    Time-series forecasting—the task of predicting future values from historical observations—is the quantitative foundation of decision-making across nearly every industry. Retailers forecast demand to stock shelves. Energy companies forecast load to schedule generation. Financial institutions forecast volatility to price options. Hospitals forecast patient admissions to staff wards. The accuracy of these forecasts directly determines whether resources are allocated efficiently or wasted at scale.

    The field has undergone substantial transformation since 2022. For decades, ARIMA and exponential smoothing dominated. They were followed by deep learning architectures—N-BEATS, Temporal Fusion Transformers, DeepAR—that challenged classical methods on complex, multivariate problems. In 2025 and 2026, the most significant shift is the emergence of foundation models pre-trained on billions of time points that can forecast series they have not previously seen, without any task-specific training. The implications for practitioners are substantial, and uncertainty about which model to use has rarely been greater.

    This guide aims to clarify that uncertainty. It traces the evolution from classical methods through deep learning to the current frontier, benchmarks the models that matter, and offers a practical framework for selecting the appropriate approach for a given problem. The treatment focuses on what works, what does not, and the reasons for each.

    Time-Series Forecasting: Model Evolution ARIMA / ETS 1970s–2010s Statistical LSTM DeepAR 2018–2021 Deep Learning Patch TST / iTrans 2022–2023 Deep Learning Transformer Era Foundation Models 2024–Present Zero-shot / Pre-trained

    Why Time-Series Forecasting Matters More Than Ever

    The volume of time-stamped data generated globally has expanded sharply. IoT sensors, financial markets, application telemetry, social media engagement metrics, weather stations, and wearable health devices all produce continuous streams of sequential observations. Organisations that aim to derive value from this data require not only appropriate forecasting models but also suitable databases for storing preprocessed time-series data and robust pipelines for moving data between systems. The International Data Corporation estimates that the global datasphere will exceed 180 zettabytes by 2025, with a substantial portion of that data being temporal.

    Volume alone, however, does not explain why forecasting has become more important. Three structural trends are increasing demand for accurate predictions:

    Just-in-time operations. Modern supply chains, cloud infrastructure, and service delivery systems operate with minimal slack. Real-time complex event processing pipelines built on Apache Flink are increasingly paired with forecasting models to detect anomalies as they occur. Amazon’s fulfilment network, Uber’s driver allocation, and Netflix’s content delivery all depend on accurate short-term forecasts to match supply with demand in near real time. Forecast errors of even 10% result in either costly over-provisioning or customer-visible failures.

    Renewable energy integration. As solar and wind generation transitions from supplementary to primary energy sources, grid operators must forecast intermittent generation with high accuracy to maintain stability. A 5% error in the solar generation forecast for a large grid can mean the difference between smooth operation and emergency natural gas peaking, with associated costs measured in millions of dollars and unnecessary emissions.

    Algorithmic decision-making at scale. Automated systems, ranging from algorithmic trading to dynamic pricing and autonomous vehicle planning, consume forecasts as inputs to decisions that execute without human review. The performance ceiling of these systems is bounded by the accuracy of their underlying forecasts.

    Key Takeaway: Time-series forecasting has evolved from a quarterly planning exercise carried out by analysts into an operational capability that runs continuously, feeds automated systems, and directly affects revenue and reliability. The standard for accuracy, and the cost of inaccuracy, has rarely been higher.

    Classical Foundations That Still Work

    Before turning to transformers and foundation models, it is important to acknowledge that classical statistical methods remain highly competitive on many forecasting problems. The 2022 M5 competition and subsequent analyses have repeatedly shown that simple methods, properly tuned, often match or surpass complex deep learning models on univariate and low-dimensional problems.

    ARIMA and SARIMA

    AutoRegressive Integrated Moving Average (ARIMA) models capture three components of a time series: autoregressive behaviour (current values depend on past values), differencing (to achieve stationarity), and moving average effects (current values depend on past forecast errors). The seasonal variant, SARIMA, adds explicit seasonal terms.

    ARIMA’s principal strengths are its theoretical foundation and interpretability: every parameter carries a clear statistical meaning. Its weakness is that it assumes linear relationships and handles only univariate series. For a single well-behaved time series with clear trend and seasonality (monthly sales, daily temperature), ARIMA remains a strong, fast, and interpretable baseline. When working with sensor data at scale, pairing ARIMA with a sound metadata management strategy for facility and sensor signals ensures that the appropriate model can be tracked against each data stream.

    Exponential Smoothing (ETS)

    Exponential Smoothing State Space models (ETS) decompose a time series into error, trend, and seasonal components, each of which can be additive or multiplicative. The Holt-Winters method, a specific ETS configuration with additive or multiplicative trend and seasonality, is among the most widely deployed forecasting models in industry, particularly in retail demand planning.

    Prophet

    Prophet (Taylor and Letham, 2018, Meta) was designed for business forecasting at scale. It decomposes time series into trend, seasonality (multiple periods), and holiday effects, fitted using a Bayesian approach. Prophet’s principal innovation was practical: it handles missing data gracefully, automatically detects changepoints in trend, and allows users to inject domain knowledge (holidays, known events) without statistical expertise. While no longer the most accurate option, Prophet remains one of the fastest paths from raw data to a reasonable forecast for business metrics.

    from prophet import Prophet
    import pandas as pd
    
    # Prophet requires a DataFrame with 'ds' (date) and 'y' (value) columns
    df = pd.DataFrame({'ds': dates, 'y': values})
    
    model = Prophet(
        yearly_seasonality=True,
        weekly_seasonality=True,
        daily_seasonality=False,
        changepoint_prior_scale=0.05,  # Controls trend flexibility
    )
    model.add_country_holidays(country_name='US')
    model.fit(df)
    
    # Forecast 90 days ahead
    future = model.make_future_dataframe(periods=90)
    forecast = model.predict(future)
    
    # forecast contains: yhat, yhat_lower, yhat_upper (prediction intervals)
    

    StatsForecast: Classical Methods at Scale

    The StatsForecast library from Nixtla warrants particular attention. It provides highly optimised implementations of classical methods (AutoARIMA, ETS, Theta, CES, MSTL) that run 100 to 1,000 times faster than traditional implementations. This speed advantage permits the fitting of individual models per time series across thousands of series, which often yields better results than a single complex model fitted globally.

    from statsforecast import StatsForecast
    from statsforecast.models import (
        AutoARIMA, AutoETS, AutoTheta, MSTL, SeasonalNaive
    )
    
    # Fit multiple models simultaneously across many series
    sf = StatsForecast(
        models=[
            AutoARIMA(season_length=7),
            AutoETS(season_length=7),
            AutoTheta(season_length=7),
            MSTL(season_lengths=[7, 365]),  # Weekly + yearly seasonality
            SeasonalNaive(season_length=7),  # Baseline
        ],
        freq='D',
        n_jobs=-1,  # Parallelize across all CPU cores
    )
    
    # df must have columns: unique_id, ds, y
    forecasts = sf.forecast(df=train_df, h=30)  # 30-day forecast
    

    Gradient Boosting for Time Series: An Underused Practitioner Tool

    An important fact about practical forecasting that often receives insufficient attention is that gradient-boosted decision trees—LightGBM, XGBoost, CatBoost—applied to time-series features often outperform both classical statistical models and deep learning on tabular-structured forecasting problems. This approach, sometimes referred to as “ML forecasting” or “feature-based forecasting,” operates by converting the time-series problem into a supervised regression problem.

    The decisive step is feature engineering: instead of feeding raw time-series values to the model, the practitioner constructs features that capture temporal patterns:

    import lightgbm as lgb
    import pandas as pd
    import numpy as np
    
    def create_time_features(df, target_col='y', lags=[1, 7, 14, 28]):
        """Create temporal features for gradient boosting."""
        result = df.copy()
    
        # Calendar features
        result['dayofweek'] = result['ds'].dt.dayofweek
        result['month'] = result['ds'].dt.month
        result['dayofyear'] = result['ds'].dt.dayofyear
        result['weekofyear'] = result['ds'].dt.isocalendar().week.astype(int)
        result['is_weekend'] = (result['dayofweek'] >= 5).astype(int)
    
        # Lag features (past values)
        for lag in lags:
            result[f'lag_{lag}'] = result[target_col].shift(lag)
    
        # Rolling statistics
        for window in [7, 14, 30]:
            result[f'rolling_mean_{window}'] = (
                result[target_col].shift(1).rolling(window).mean()
            )
            result[f'rolling_std_{window}'] = (
                result[target_col].shift(1).rolling(window).std()
            )
    
        # Expanding mean (long-term average up to current point)
        result['expanding_mean'] = result[target_col].shift(1).expanding().mean()
    
        return result.dropna()
    
    features_df = create_time_features(df)
    feature_cols = [c for c in features_df.columns if c not in ['ds', 'y']]
    
    model = lgb.LGBMRegressor(
        n_estimators=1000,
        learning_rate=0.05,
        num_leaves=31,
        subsample=0.8,
    )
    model.fit(features_df[feature_cols], features_df['y'])
    

    The reason this approach is effective is that gradient boosting captures complex nonlinear relationships between features—including interactions among calendar effects, lagged values, and rolling statistics that linear models cannot represent. Feature engineering renders the temporal structure explicit, allowing tree-based models to discover patterns such as “demand is high on Fridays in December when the previous week’s demand was above average”—patterns that require multiple conditional splits and that ARIMA cannot represent at all.

    Tip: In Kaggle time-series competitions, LightGBM with careful feature engineering has won more forecasting competitions than any deep learning model. The combination is fast to train, easy to interpret (via feature importance), handles missing data natively, and scales well to millions of time series. For a production forecasting system without a clear starting point, LightGBM with temporal features is a strong default.

    The Deep Learning Era: N-BEATS, N-HiTS, and TFT

    N-BEATS: Neural Basis Expansion (2020)

    N-BEATS (Oreshkin et al., 2020) was the first deep learning model to conclusively surpass statistical methods on the M4 competition benchmark—a landmark result. Its architecture is elegantly simple: a deep stack of fully-connected blocks, each producing a partial forecast and a partial backcast (reconstruction of the input). The final forecast is the sum of all blocks’ partial forecasts.

    N-BEATS exists in two variants: a generic architecture in which blocks learn arbitrary basis functions, and an interpretable architecture in which blocks are constrained to learn trend and seasonality components, producing decompositions analogous to those of classical methods but with the expressiveness of deep learning. The interpretable variant is particularly valuable in business settings where stakeholders must understand why the model forecasts what it does.

    N-HiTS: Hierarchical Interpolation (2023)

    N-HiTS (Challu et al., 2023) extends N-BEATS with a multi-rate signal sampling approach. Different blocks in the stack process the input at different temporal resolutions: some blocks focus on long-term trends (downsampled signal), while others focus on short-term fluctuations (full-resolution signal). This hierarchical approach significantly improves long-horizon forecasting accuracy while reducing computational cost by a factor of three to five compared with N-BEATS.

    Temporal Fusion Transformer (2021)

    Temporal Fusion Transformer (TFT) (Lim et al., 2021, Google) is designed for the real-world complexity that pure time-series models ignore: it jointly processes static metadata (store location, product category), known future inputs (holidays, promotions, day of week), and observed past values. TFT uses attention mechanisms to learn which historical time steps are most relevant for each forecast horizon and produces interpretable multi-horizon forecasts with prediction intervals.

    TFT’s architecture includes a variable selection network that learns which input features are most important, providing built-in feature importance that other deep models lack. For multi-horizon forecasting with rich covariate information, TFT remains one of the strongest available models.

    DeepAR: Probabilistic Forecasting at Scale (2020)

    DeepAR (Salinas et al., 2020, Amazon) takes a different approach: it trains a single autoregressive RNN model across all time series in a dataset, learning shared patterns while generating probabilistic (not point) forecasts. DeepAR outputs full probability distributions rather than single values, enabling decision-makers to reason about uncertainty rather than only expected outcomes.

    DeepAR’s “global model” approach is especially powerful when individual series are short or sparse. A new product with only 10 days of sales data benefits from patterns learned across millions of other products. This cold-start capability is essential in retail and e-commerce forecasting.

    PatchTST: When Vision Meets Time Series (ICLR 2023)

    PatchTST (Nie et al., 2023) brought a key insight from computer vision to time-series forecasting. Rather than treating each time step as a separate token (computationally expensive and prone to attention dilution), PatchTST groups consecutive time steps into patches, analogously to the way Vision Transformers (ViT) group image pixels into patches.

    A time series of 512 points, with a patch size of 16, becomes a sequence of 32 tokens, each representing a local temporal pattern. The transformer’s self-attention then operates over these 32 patches rather than 512 individual points, substantially reducing computational cost while preserving the model’s ability to capture long-range dependencies between patches.

    PatchTST also introduced channel-independent processing: in multivariate settings, each variable is processed by the same transformer backbone independently, with shared weights. This counterintuitive choice—ignoring cross-variable correlations—improves generalisation substantially for many datasets, because it prevents the model from overfitting to spurious inter-variable correlations in training data.

    Model Year Architecture Key Innovation Best For
    N-BEATS 2020 Fully connected stacks Basis expansion, interpretable variant Univariate, interpretability needed
    DeepAR 2020 Autoregressive RNN Global model, probabilistic output Many related series, cold start
    TFT 2021 Transformer + variable selection Multi-horizon, rich covariates Complex business forecasting
    N-HiTS 2023 Hierarchical FC stacks Multi-rate signal sampling Long-horizon forecasting
    PatchTST 2023 Patched Transformer Patching + channel independence Long-range multivariate

     

    iTransformer: Inverting the Attention Paradigm (ICLR 2024)

    iTransformer (Liu et al., 2024, Tsinghua) poses a pointed question: whether transformers have been applied to time series incorrectly to date.

    In standard transformer-based forecasting, each time step is a token, and the model applies self-attention across time, with each time step attending to every other time step. The feed-forward layers process individual time-step features, while the attention mechanism captures temporal dependencies.

    iTransformer inverts this arrangement: each variable (channel) becomes a token, and the entire time series of that variable becomes the token’s embedding. Self-attention now operates across variables, learning which variables are relevant to each other, while the feed-forward layers process temporal patterns within each variable.

    This inversion is highly effective. On standard multivariate benchmarks (ETTh, ETTm, Weather, Electricity, Traffic), iTransformer achieves leading or near-leading results while being simpler to implement than many competitors. The implication is that, for multivariate forecasting, learning cross-variable relationships through attention is more important than learning temporal patterns through attention; temporal patterns can be captured adequately by simpler feed-forward networks.

    # iTransformer conceptual structure (simplified)
    # Standard Transformer: tokens = time steps, embedding = features
    # iTransformer:          tokens = features,   embedding = time steps
    
    import torch.nn as nn
    
    class iTransformerLayer(nn.Module):
        def __init__(self, n_vars, seq_len, d_model):
            super().__init__()
            # Project each variable's full time series into d_model dims
            self.embed = nn.Linear(seq_len, d_model)  # Per-variable
    
            # Attention operates ACROSS variables (not time)
            self.attention = nn.MultiheadAttention(d_model, nhead=8)
    
            # FFN processes temporal patterns within each variable
            self.ffn = nn.Sequential(
                nn.Linear(d_model, d_model * 4),
                nn.GELU(),
                nn.Linear(d_model * 4, d_model),
            )
    
        def forward(self, x):
            # x: (batch, seq_len, n_vars)
            # Transpose to (batch, n_vars, seq_len), embed
            x = x.permute(0, 2, 1)           # (B, V, T)
            x = self.embed(x)                 # (B, V, D)
            x = x.permute(1, 0, 2)           # (V, B, D) for attention
            attn_out, _ = self.attention(x, x, x)  # Cross-variable attention
            x = x + attn_out
            x = x + self.ffn(x)              # Temporal pattern refinement
            return x
    

    Foundation Models: Zero-Shot Forecasting Arrives

    The paradigm shift that has drawn the most attention in the forecasting community is the emergence of foundation models capable of forecasting time series on which they were never trained. This capability is analogous to GPT’s ability to answer questions on topics it was not explicitly fine-tuned for: the model has learned general patterns of sequential data from substantial pre-training and applies those patterns to new inputs at inference time.

    TimesFM (Google, 2024)

    TimesFM is a 200M-parameter decoder-only transformer pre-trained on approximately 100 billion time points from Google Trends, Wikipedia page views, synthetic data, and various public datasets. Its architecture uses input patching (similar to PatchTST) with variable patch sizes, allowing it to handle different granularities and frequencies.

    TimesFM’s zero-shot performance is notable: on datasets it has never previously seen, it matches or exceeds supervised models trained specifically on those datasets. Google’s internal evaluations indicate that TimesFM outperforms tuned ARIMA and ETS on 60% to 70% of retail forecasting series, without a single gradient update on retail data.

    import timesfm
    
    # Load the pre-trained model
    tfm = timesfm.TimesFm(
        hparams=timesfm.TimesFmHparams(
            backend="gpu",
            per_core_batch_size=32,
            horizon_len=128,
        ),
        checkpoint=timesfm.TimesFmCheckpoint(
            huggingface_repo_id="google/timesfm-1.0-200m-pytorch"
        ),
    )
    
    # Zero-shot forecast — no training required
    point_forecast, experimental_quantile_forecast = tfm.forecast(
        inputs=[historical_series_1, historical_series_2],  # List of arrays
        freq=[0, 0],  # 0=high-freq, 1=medium, 2=low
    )
    # Returns forecasts for all input series simultaneously
    

    Chronos (Amazon, 2024)

    Chronos tokenises continuous time-series values into discrete bins using mean scaling and quantisation, then applies a T5 language model architecture. By treating forecasting as a language problem—predicting the next token given the sequence so far—Chronos uses decades of NLP architecture innovations and training procedures.

    Chronos offers multiple sizes (20M to 710M parameters) and produces probabilistic forecasts natively, with each prediction representing a distribution over possible future values. The model is well suited to applications where uncertainty quantification matters (inventory planning, risk management, resource allocation).

    A noteworthy feature is synthetic data augmentation during pre-training. Chronos generates millions of synthetic time series using Gaussian processes with diverse kernels, ensuring that the model has been exposed to a wide range of temporal patterns—seasonal, trending, noisy, smooth, and multi-scale—even where the real-world training data does not cover all of them.

    Moirai (Salesforce, 2024)

    Moirai (Woo et al., 2024) is a universal forecasting model designed to handle any time series regardless of frequency, number of variables, or forecast horizon. Its architecture addresses a key limitation of other foundation models: distribution shift across datasets.

    Different time series have radically different scales and statistical properties. Server CPU usage ranges from 0 to 100%. Stock prices range from 1 to 5,000 USD. Energy consumption may be measured in megawatts. Moirai uses a mixture distribution output—predicting parameters of a mixture of distributions rather than point values—that adapts naturally to different scales and distributional shapes without manual normalisation.

    Moirai also introduces Any-Variate Attention, which allows the model to process multivariate time series with arbitrary numbers of variables at inference time, even when the model was pre-trained on series of different dimensionality. This flexibility makes Moirai one of the most versatile foundation models available.

    TimeMixer++ and TSMixer (2024-2025)

    TSMixer (Google, 2023) demonstrated that a simple MLP-Mixer architecture, alternating between time-mixing (across time steps) and feature-mixing (across variables), achieves results competitive with transformers while being significantly faster. TimeMixer++ extends this with multi-scale decomposition, processing different frequency components through separate mixing paths.

    These mixer-based architectures are particularly attractive for production deployment because their computational complexity scales linearly with sequence length (rather than quadratically as in standard attention), which makes them practical for very long context windows and high-frequency data.

    Foundation Model Organization Parameters Open Source Output Type Multivariate
    TimesFM Google 200M Yes Point + quantiles Per-channel
    Chronos Amazon 20M–710M Yes Probabilistic Per-channel
    Moirai Salesforce 14M–311M Yes Mixture distribution Native multivariate
    MOMENT CMU 40M–385M Yes Point Per-channel
    TimeGPT Nixtla Undisclosed No (API) Point + intervals Per-channel
    Timer Tsinghua 67M Yes Autoregressive Per-channel

     

    Caution: Foundation model hype is real, but so are their limitations. Most foundation models process each variable independently (per-channel) and do not capture cross-variable correlations. For problems in which inter-variable relationships are critical (for example, predicting energy demand from weather, price, and grid load), a trained multivariate model such as TFT or iTransformer may still outperform. Foundation models also struggle with domain-specific patterns they have not encountered in pre-training: a financial time series with quarterly earnings seasonality may not be well represented in pre-training data dominated by daily and weekly patterns.

    Benchmarks: How Models Actually Compare

    The most widely used benchmarks for long-term forecasting are the ETT datasets (Electricity Transformer Temperature), Weather, Electricity, and Traffic. The following table presents representative results using Mean Squared Error (MSE), where lower values are better, on standard prediction horizons.

    Model ETTh1 (96) ETTh1 (720) Weather (96) Electricity (96) Traffic (96)
    ARIMA 0.423 0.618 0.284 0.227 0.662
    N-HiTS 0.384 0.464 0.166 0.169 0.415
    PatchTST 0.370 0.449 0.149 0.129 0.370
    iTransformer 0.355 0.434 0.141 0.126 0.360
    TimesFM (zero-shot) 0.391 0.478 0.168 0.155 0.410
    Chronos-Base (zero-shot) 0.398 0.491 0.172 0.160 0.425

     

    Model Family Trade-offs: Statistical vs Deep Learning vs Foundation Statistical Deep Learning Foundation Models Accuracy Training Data needs Interpretability Uncertainty Cold start Good (univariate) Seconds Minimal High Native (ETS) Weak Best (multivariate) Hours–days Large dataset Medium (TFT) Requires setup Poor Competitive Zero (zero-shot) None (zero-shot) Low Native (Chronos) Excellent

    Numbers are approximate and representative. Lower MSE is better. (96) and (720) denote the forecast horizon length. Results compiled from published papers and reproductions.

    Several patterns emerge from the benchmarks:

    • iTransformer and PatchTST lead among supervised models on most multivariate long-range benchmarks, with iTransformer holding a slight edge on datasets in which cross-variable correlations are important.
    • Foundation models (zero-shot) are competitive but do not yet surpass trained models. TimesFM and Chronos typically fall between classical methods and the best supervised deep models, which is notable given the absence of training but not dominant. The gap narrows on datasets whose patterns are well represented in pre-training data.
    • Classical methods remain surprisingly strong on univariate series, particularly when combined with ensembling (averaging forecasts from AutoARIMA, ETS, and Theta). The overhead of deep learning is not always justified.
    • The performance gap widens at longer horizons. The advantage of deep models over classical methods is largest at prediction horizons of 336 steps or more, where complex temporal patterns compound and the assumptions of statistical models break down.

    Practical Model Selection Guide

    Given this landscape, how should a practitioner choose the right model for a given problem? The following decision framework draws on practical constraints:

    Scenario 1: Quick deployment with no training-data infrastructure

    Use: Foundation model (Chronos or TimesFM) in zero-shot mode

    When forecasts are required immediately and investment in a training pipeline is not feasible, foundation models deliver competitive accuracy with no setup. Install the library, feed in the data, and obtain forecasts. This option is well suited to proofs of concept, new data streams, and situations in which the cost of deploying a custom model exceeds the cost of slightly reduced accuracy.

    Scenario 2: Thousands of univariate series, where speed and reliability are required

    Use: StatsForecast (AutoARIMA + AutoETS + AutoTheta ensemble)

    For large-scale retail demand forecasting, financial time series, or IoT monitoring in which each series is relatively independent, fitting per-series statistical models is fast, reliable, and often the most accurate approach. StatsForecast’s optimised implementations make this feasible even for millions of series.

    Scenario 3: Multivariate with rich covariates (promotions, holidays, metadata)

    Use: Temporal Fusion Transformer or LightGBM with temporal features

    When the forecast depends on external factors—promotional calendars, weather forecasts, economic indicators, or product attributes—a model that ingests covariates natively is required. TFT handles this elegantly with built-in variable selection. LightGBM with engineered features is faster to iterate and often equally accurate.

    Scenario 4: Long-horizon multivariate forecasting where accuracy is paramount

    Use: iTransformer or PatchTST

    For applications in which prediction accuracy directly affects high-value decisions (energy trading, infrastructure capacity planning, financial risk management), investment in training a supervised deep model on historical data is appropriate. iTransformer and PatchTST represent the current accuracy frontier for long-range multivariate forecasting.

    Scenario 5: Uncertainty quantification is critical

    Use: Chronos (probabilistic) or DeepAR

    When prediction intervals are required rather than only point forecasts, Chronos provides calibrated probabilistic forecasts out of the box, and DeepAR produces full probability distributions trained on the user’s specific data. These methods are essential for inventory optimisation (balancing stockout against overstock risk) and financial risk management.

    Tip: The most consistently effective practical advice for forecasting accuracy is to ensemble. Averaging forecasts from three to five diverse models (a statistical model, a gradient boosting model, and a deep learning model) consistently outperforms any individual model. The M-series competitions have demonstrated this repeatedly. Ensembling is unglamorous, but it produces better results than almost any other practice.

    Implementation: End-to-End Forecasting Pipeline

    A complete forecasting pipeline involves far more than model selection. The architecture used in production systems is as follows:

    # Production forecasting pipeline using NeuralForecast + StatsForecast
    from neuralforecast import NeuralForecast
    from neuralforecast.models import NHITS, PatchTST, TimesNet
    from statsforecast import StatsForecast
    from statsforecast.models import AutoARIMA, AutoETS, AutoTheta
    import pandas as pd
    import numpy as np
    
    # Step 1: Data preparation
    # df must have columns: unique_id, ds, y
    train_df = df[df['ds'] < '2026-01-01']
    test_df = df[df['ds'] >= '2026-01-01']
    horizon = 30  # 30-day forecast
    
    # Step 2: Statistical models (fast, per-series)
    sf = StatsForecast(
        models=[
            AutoARIMA(season_length=7),
            AutoETS(season_length=7),
            AutoTheta(season_length=7),
        ],
        freq='D',
        n_jobs=-1,
    )
    stat_forecasts = sf.forecast(df=train_df, h=horizon)
    
    # Step 3: Deep learning models (slower, more expressive)
    nf = NeuralForecast(
        models=[
            NHITS(
                input_size=180,
                h=horizon,
                max_steps=1000,
                n_pool_kernel_size=[4, 4, 4],
            ),
            PatchTST(
                input_size=512,
                h=horizon,
                max_steps=1000,
                patch_len=16,
            ),
        ],
        freq='D',
    )
    nf.fit(df=train_df)
    neural_forecasts = nf.predict()
    
    # Step 4: Ensemble (simple average — often the best approach)
    combined = stat_forecasts.merge(neural_forecasts, on=['unique_id', 'ds'])
    model_cols = [c for c in combined.columns
                  if c not in ['unique_id', 'ds']]
    combined['ensemble'] = combined[model_cols].mean(axis=1)
    
    # Step 5: Evaluate
    from utilsforecast.losses import mae, mse, smape
    evaluation = {
        'MAE': mae(test_df['y'], combined['ensemble']),
        'MSE': mse(test_df['y'], combined['ensemble']),
        'sMAPE': smape(test_df['y'], combined['ensemble']),
    }
    print(f"Ensemble performance: {evaluation}")
    

    End-to-End Forecasting Pipeline Historical Data Clean · Validate Feature Engineering Lags · Calendar · Covariates Model(s) Statistical · ML · DL Foundation · Ensemble Forecast Output Point · Intervals · Dist. Evaluation MAE · MSE · sMAPE Backtesting · Monitoring Continuous monitoring → retrain on drift

    Important pipeline components beyond the model include:

    • Data quality checks. Missing values, duplicates, timezone inconsistencies, and outliers in training data directly degrade forecast quality. Automated data validation before model training is essential. If the time-series data originates from InfluxDB, an InfluxDB-to-Iceberg pipeline with Telegraf can centralise and validate data before it reaches the models.
    • Cross-validation for time series. Random train-test splits should never be used for time series. Use expanding-window or sliding-window cross-validation that respects temporal ordering. The utilsforecast library provides optimised implementations.
    • Forecast reconciliation. When forecasts exist at multiple hierarchical levels (store, region, national), they must be coherent: the sum of store forecasts should equal the regional forecast. Methods such as MinTrace reconciliation ensure consistency.
    • Backtesting and monitoring. Production forecasts must be continuously evaluated against actuals. Forecast accuracy that degrades over time, owing to concept drift, data pipeline issues, or regime changes, requires automated detection and model-retraining triggers.

    The Future of Forecasting

    Time-series forecasting sits at an interesting juncture. Classical methods remain competitive for many problems. Deep learning models set the accuracy frontier for complex, multivariate, long-horizon tasks. Foundation models promise to make forecasting more broadly accessible by eliminating the need for per-dataset training. Meanwhile, gradient boosting consistently outperforms both on many real-world, feature-rich problems. For teams building production systems, pairing forecasting with Apache Kafka for multivariate time-series streaming provides the real-time data backbone these models require.

    Several trends will shape the next wave of innovation:

    Foundation model fine-tuning is bridging the gap between zero-shot and fully supervised performance. The pattern is to pre-train on billions of diverse time points and then fine-tune on a specific domain with as few as a few hundred data points. Early results indicate that fine-tuned Chronos and TimesFM can match or exceed fully supervised models using only a fraction of the training data.

    Conformal prediction for calibrated uncertainty is replacing ad hoc prediction interval methods. Conformal prediction provides distribution-free, mathematically guaranteed coverage intervals: when 95% intervals are requested, they contain the true value 95% of the time, regardless of the underlying data distribution. Libraries such as MAPIE and EnbPI make this practical for production use.

    LLM-enhanced forecasting is an emerging research direction in which large language models augment numerical forecasts with textual context. A model that incorporates information such as “Black Friday is next week” or “a competitor has announced a price cut”—information present in text but not in numerical time-series history—can produce forecasts that purely numerical models cannot match. Early papers from Amazon and Google report promising results for retail demand forecasting.

    Real-time adaptive models that continuously update their parameters as new data arrives (online learning) are becoming practical for streaming applications. Rather than periodic batch retraining, the model learns from each new observation in real time, automatically adapting to concept drift without human intervention.

    The most important practical lesson from the current landscape is that the best forecasting system is not the best model but the best pipeline. Data quality, feature engineering, cross-validation, ensembling, monitoring, and retraining together determine forecast accuracy more than any individual model choice. Teams that invest in pipeline infrastructure consistently outperform teams that chase the latest model architecture. The recommended approach is to begin with a simple, well-engineered pipeline and add complexity only when measured accuracy improvements justify it. A seasonal naive baseline should always be used as a reference point, since even the most sophisticated model is of little value if it cannot improve on “same as last week.”


    References

    • Nie, Yuqi, et al. “A Time Series is Worth 64 Words: Long-term Forecasting with Transformers.” (PatchTST) ICLR 2023.
    • Liu, Yong, et al. “iTransformer: Inverted Transformers Are Effective for Time Series Forecasting.” ICLR 2024.
    • Das, Abhimanyu, et al. “A Decoder-Only Foundation Model for Time-Series Forecasting.” (TimesFM) ICML 2024.
    • Ansari, Abdul Fatir, et al. “Chronos: Learning the Language of Time Series.” arXiv:2403.07815, 2024.
    • Woo, Gerald, et al. “Unified Training of Universal Time Series Forecasting Transformers.” (Moirai) ICML 2024.
    • Oreshkin, Boris N., et al. “N-BEATS: Neural Basis Expansion Analysis for Interpretable Time Series Forecasting.” ICLR 2020.
    • Challu, Cristian, et al. “N-HiTS: Neural Hierarchical Interpolation for Time Series Forecasting.” AAAI 2023.
    • Lim, Bryan, et al. “Temporal Fusion Transformers for Interpretable Multi-horizon Time Series Forecasting.” International Journal of Forecasting, 2021.
    • Salinas, David, et al. “DeepAR: Probabilistic Forecasting with Autoregressive Recurrent Networks.” International Journal of Forecasting, 2020.
    • Goswami, Mononito, et al. “MOMENT: A Family of Open Time-Series Foundation Models.” ICML 2024.
    • Wu, Haixu, et al. “TimesNet: Temporal 2D-Variation Modeling for General Time Series Analysis.” ICLR 2023.
    • Taylor, Sean J. and Benjamin Letham. “Forecasting at Scale.” (Prophet) The American Statistician, 2018.
    • NeuralForecast GitHub, Production deep learning forecasting
    • StatsForecast GitHub—Lightning-fast statistical forecasting
    • Time-Series-Library (THU)—Unified deep learning framework
    • Chronos GitHub Repository
    • TimesFM GitHub Repository
  • Time-Series Anomaly Detection in 2026: From Classical Methods to Foundation Models

    Summary

    What this post covers: The full landscape of time-series anomaly detection in 2026, from classical statistical methods through transformer architectures to zero-shot foundation models like TimesFM, Chronos, and MOMENT, with practical guidance on choosing the right model.

    Key insights:

    • Time-series anomaly detection is uniquely hard because “anomalous” is context-dependent, labels are scarce (often less than 0.01% of data), normal behavior drifts over time, and the most dangerous anomalies often manifest only as subtle multivariate correlations.
    • Foundation models pre-trained on 100B+ time points (TimesFM, Chronos) deliver competitive zero-shot anomaly detection without any per-dataset training, collapsing time-to-deployment from weeks to hours.
    • Classical methods (Isolation Forest, Matrix Profile, seasonal decomposition) remain surprisingly competitive and should always be benchmarked as baselines before reaching for deep learning.
    • Different anomaly types (point, contextual, collective, trend, shapelet) require different model architectures, no single model wins across all five categories.
    • The field is now shifting from detection alone toward integrated detect-explain-remediate systems combining LLMs, multimodal foundation models, and edge deployment of distilled detectors.

    Main topics: Why Time-Series Anomaly Detection Is Harder Than Often Assumed, A Taxonomy of Time-Series Anomalies, Classical Approaches: Where It All Started, The Deep Learning Revolution in Anomaly Detection, Transformer-Based Models: The Current Best, Foundation Models for Time Series: The 2025-2026 Frontier, Benchmarks and Real-World Performance, Practical Guide: Choosing the Right Model for the Problem, Implementation: Building an Anomaly Detection Pipeline, Where the Field Is Heading, References.

    On 19 July 2024, a faulty content update from CrowdStrike caused 8.5 million Windows machines to crash simultaneously, producing the largest IT outage in history. Airlines grounded flights, hospitals postponed surgeries, and banks froze transactions. The total economic damage exceeded 10 billion USD. The root cause was a single faulty configuration file pushed to production. An anomaly detection system monitoring the deployment’s telemetry—CPU spikes, crash rates, memory patterns—could have flagged the cascading failure within seconds and triggered an automatic rollback before more than 0.1% of those machines were affected.

    The benefit is not hypothetical. Companies such as Netflix, Uber, and Meta operate real-time anomaly detection systems that identify precisely these patterns: sudden deviations in request latency, error rates, transaction volumes, or system metrics indicating that a problem has arisen before users notice it. The difference between detection in 30 seconds and detection in 30 minutes can be the difference between a minor incident and a high-profile failure.

    Time-series anomaly detection—the task of identifying unusual patterns in sequential, timestamped data—has undergone substantial transformation over the past three years. Classical statistical methods that served practitioners for decades are now being augmented, and in some cases replaced, by deep learning architectures, transformer-based models, and, most recently, pre-trained foundation models that can detect anomalies in time series they have never encountered before, without any task-specific training. The pace of innovation has been notable, and the gap between research results and production performance is narrowing rapidly.

    This guide surveys the full landscape, from classical approaches that remain surprisingly competitive, through the deep learning developments of 2020 to 2024, to the foundation model frontier of 2025 and 2026. For practitioners building anomaly detection for infrastructure monitoring, financial fraud detection, predictive maintenance, or healthcare, understanding these models—their strengths, limitations, and practical trade-offs—is essential.

    Why Time-Series Anomaly Detection Is Harder Than Often Assumed

    Detecting anomalies in tabular data is relatively straightforward: a transaction of 50,000 USD when the customer’s average is 200 USD is clearly unusual. Time-series anomaly detection is fundamentally harder because the definition of “unusual” depends on temporal context: patterns that are normal at one time may be anomalous at another.

    Consider server CPU usage. A spike to 95% utilisation at 3 AM may be entirely normal—it is when the batch processing job runs. The same spike at 3 PM, when only light API traffic is expected, may indicate a runaway process or a denial-of-service attack. A gradual drift from a 40% baseline to 60% over six weeks may indicate a memory leak that will eventually cause a crash. Each of these requires the detection system to understand not only the current value but also its relationship to seasonal patterns, trends, and the broader temporal context.

    The challenges fall into several categories:

    Rarity of labelled anomalies. In most real-world datasets, anomalies represent less than 1% of observations and often less than 0.01%. Supervised learning approaches struggle because the classes are so imbalanced. Most current best methods therefore operate in unsupervised or semi-supervised settings, learning the structure of normal behaviour and flagging deviations.

    Concept drift. The definition of “normal” changes over time. A system that learned normal patterns from January data may flag entirely healthy February patterns as anomalous if the business has grown, the user base has shifted, or the infrastructure has been upgraded. Models must adapt to evolving baselines without losing sensitivity to genuine anomalies.

    Multivariate dependencies. Modern systems generate hundreds or thousands of metrics simultaneously. An anomaly may not be visible in any single metric—CPU appears normal, memory appears normal, disk I/O appears normal—yet the simultaneous combination of all three at slightly elevated levels indicates an emerging problem. Capturing these inter-metric correlations is where deep learning approaches surpass classical univariate methods.

    Key Takeaway: Time-series anomaly detection is difficult because “anomalous” is context-dependent, labelled data is scarce, normal behaviour evolves, and the most consequential anomalies often manifest only as subtle correlations across multiple variables. Models that handle all four challenges simultaneously are rare, which accounts for the continued rapid advancement of the field.

    A Taxonomy of Time-Series Anomalies

    Before selecting a model, a practitioner must identify the type of anomaly under consideration. Different model architectures perform differently across anomaly types:

    Anomaly Type Description Example Best Detection Approach
    Point anomaly A single observation far from expected Sudden CPU spike to 100% Statistical thresholds, Isolation Forest
    Contextual anomaly Normal value in wrong context High traffic at 4 AM (normally low) Seasonal decomposition, LSTM, Transformer
    Collective anomaly A sequence of observations anomalous together Sustained elevated error rate for 10 minutes Sliding-window models, sequence-to-sequence
    Trend anomaly Gradual shift from expected trajectory Memory usage growing 2% weekly (leak) Change-point detection, trend decomposition
    Shapelet anomaly Unusual pattern shape in a subsequence Abnormal ECG waveform morphology Matrix Profile, deep autoencoders

     

    Three Types of Time-Series Anomalies Point Anomaly anomaly time Contextual Anomaly wrong context night (low expected) day Collective Anomaly sustained shift time Normal signal Anomalous segment Point anomaly Contextual anomaly

    Classical Approaches: Where It All Started

    Before deep learning, time-series anomaly detection relied on statistical methods that remain relevant and surprisingly competitive for many use cases. Understanding these foundations is essential: they serve as baselines, they are interpretable, and they run efficiently without GPU infrastructure.

    Statistical and Decomposition Methods

    STL Decomposition with Residual Thresholding. Seasonal-Trend decomposition using LOESS (STL) separates a time series into trend, seasonal, and residual components. Anomalies are identified by flagging residuals that exceed a threshold (typically three standard deviations). The method is simple, interpretable, and handles seasonality well, which makes it well suited to business metrics such as daily active users or hourly revenue.

    ARIMA-based Detection. AutoRegressive Integrated Moving Average models forecast the next value based on historical patterns. Observations that deviate significantly from the forecast are flagged. ARIMA performs well for stationary series with clear autoregressive structure but struggles with complex multi-seasonal patterns or nonlinear dynamics.

    Exponential Smoothing State Space Models (ETS). Similar in spirit to ARIMA but using exponential weighting of past observations. The Holt-Winters variant handles both trend and seasonality and remains a standard tool in production monitoring systems.

    Isolation Forest and Tree-Based Methods

    Isolation Forest (Liu et al., 2008) takes a distinctly different approach. Instead of building a model of normal behaviour and looking for deviations, it directly identifies anomalies by measuring how easy they are to isolate. Anomalous points, being different from the majority, require fewer random partitions to separate from the rest of the data. Isolation Forest is fast, scales well to high-dimensional data, and handles multivariate anomaly detection naturally.

    from sklearn.ensemble import IsolationForest
    import numpy as np
    import pandas as pd
    
    # Create windowed features from raw time series
    def create_features(series, window=24):
        features = []
        for i in range(window, len(series)):
            window_data = series[i-window:i]
            features.append({
                'mean': np.mean(window_data),
                'std': np.std(window_data),
                'min': np.min(window_data),
                'max': np.max(window_data),
                'last': window_data[-1],
                'trend': np.polyfit(range(window), window_data, 1)[0]
            })
        return pd.DataFrame(features)
    
    # Fit Isolation Forest
    features = create_features(cpu_usage_series, window=24)
    model = IsolationForest(contamination=0.01, random_state=42)
    predictions = model.fit_predict(features)
    # -1 = anomaly, 1 = normal
    

    Matrix Profile: Subsequence Analysis

    Matrix Profile (Yeh et al., 2016) computes the distance between every subsequence in a time series and its nearest neighbour, producing a profile of how distinctive each subsequence is. Subsequences with high matrix profile values—those whose nearest neighbour lies unusually far away—are anomalous. Matrix Profile is particularly effective at detecting shapelet anomalies (unusual pattern shapes) and is computationally efficient thanks to the STOMP algorithm, which computes the full matrix profile in O(n² log n) time.

    The Python library stumpy provides production-grade Matrix Profile implementations and remains one of the more underused tools in the anomaly detection practitioner’s repertoire.

    The Deep Learning Revolution in Anomaly Detection

    From approximately 2019 onward, deep learning models began consistently outperforming classical methods on complex, multivariate anomaly detection benchmarks. The central insight is that deep neural networks can learn nonlinear temporal patterns that are invisible to linear statistical models.

    LSTM Autoencoders: The First Deep Success

    The LSTM Autoencoder architecture, consisting of an encoder that compresses a time-series window into a latent representation followed by a decoder that reconstructs the original window, became the first widely adopted deep learning approach for time-series anomaly detection. The model learns to reconstruct normal patterns during training. At inference, windows with high reconstruction error are flagged as anomalous, since the model has not learned to reconstruct those patterns.

    LSTM Autoencoders handle temporal dependencies (the LSTM component) and learn expected patterns (the autoencoder objective) simultaneously. They were the standard deep approach from approximately 2019 to 2022 and remain effective for many applications.

    import torch
    import torch.nn as nn
    
    class LSTMAutoencoder(nn.Module):
        def __init__(self, n_features, hidden_size=64, n_layers=2):
            super().__init__()
            self.encoder = nn.LSTM(
                n_features, hidden_size, n_layers, batch_first=True
            )
            self.decoder = nn.LSTM(
                hidden_size, hidden_size, n_layers, batch_first=True
            )
            self.output_layer = nn.Linear(hidden_size, n_features)
    
        def forward(self, x):
            # Encode: compress the sequence
            _, (hidden, cell) = self.encoder(x)
    
            # Decode: reconstruct the sequence
            seq_len = x.size(1)
            decoder_input = hidden[-1].unsqueeze(1).repeat(1, seq_len, 1)
            decoder_out, _ = self.decoder(decoder_input)
            reconstruction = self.output_layer(decoder_out)
    
            return reconstruction
    
    # Anomaly score = reconstruction error (MSE per window)
    # High reconstruction error → anomaly
    

    GDN and GNN-Based Methods: Modelling Inter-Metric Relationships

    Graph Deviation Network (GDN) (Deng and Hooi, 2021) introduced an elegant solution for multivariate anomaly detection: model the relationships between sensors and metrics as a graph, in which each node is a time series and edges represent learned dependencies. When a metric deviates from what the graph structure predicts based on its neighbours’ values, it is flagged as anomalous.

    GDN’s principal advantage is its ability to identify anomalies that are not visible in individual metrics but manifest as broken inter-metric correlations. For example, in a server cluster, CPU and memory usage typically correlate. If CPU spikes while memory does not, or vice versa, GDN detects the correlation violation, even when both values lie individually within normal ranges.

    USAD: Unsupervised Anomaly Detection

    USAD (Audibert et al., 2020) combines autoencoders with adversarial training. Two decoder networks compete: one reconstructs the input from the latent space, while the other attempts to reconstruct the first decoder’s output. This adversarial scheme requires the autoencoders to learn sharper boundaries between normal and anomalous patterns, significantly improving detection accuracy relative to standard autoencoders. USAD is fast to train, performs well on multivariate data, and has become a popular baseline in academic benchmarks.

    Transformer-Based Models: The Current Best

    The transformer architecture, originally designed for natural language processing, has proven highly effective for time-series analysis. Its self-attention mechanism captures long-range dependencies in sequences without the vanishing gradient problems that limit RNNs and LSTMs. Several transformer-based models have set new state-of-the-art results on anomaly detection benchmarks.

    Anomaly Transformer (ICLR 2022)

    Anomaly Transformer (Xu et al., 2022) introduced a central insight: in normal time-series data, each point’s attention pattern should focus on adjacent points (the “prior-association”) and on semantically similar points elsewhere in the series (the “series-association”). These two association patterns align for normal data but diverge for anomalies. Anomaly Transformer introduces an Association Discrepancy metric that measures this divergence, providing a principled anomaly score.

    The model achieved leading results on six benchmark datasets at the time of publication and remains among the strongest methods for unsupervised multivariate anomaly detection. Its principal contribution—using attention-pattern discrepancy rather than reconstruction error as the anomaly score—represents a conceptual advance over prior autoencoder-based approaches.

    DCdetector: Dual-Attention Contrastive Learning (ICML 2023)

    DCdetector (Yang et al., 2023) builds on the association discrepancy idea with a contrastive learning framework. It creates two representations of each time step, one from a “patch-wise” attention view and one from a “channel-wise” attention view, and uses contrastive learning to maximise agreement for normal patterns and divergence for anomalies. DCdetector achieved new state-of-the-art results on multiple benchmarks, improving on Anomaly Transformer’s F1 scores by 2 to 5 points on several datasets.

    TimesNet: From Temporal to Spatial (ICLR 2023)

    TimesNet (Wu et al., 2023) takes a creative approach: it transforms 1D time-series data into 2D representations by reshaping each period (daily, weekly, and so on) into a 2D image-like tensor, and then applies 2D convolutional neural networks to capture both intra-period and inter-period patterns simultaneously. This transformation allows TimesNet to use the feature extraction capabilities of CNNs, originally developed for computer vision, on temporal data.

    TimesNet is a general-purpose time-series model (it handles forecasting, classification, and anomaly detection), and its multi-task capability makes it a strong choice for teams that require a single architecture for multiple analytical needs.

    Model Year Core Idea Strengths Limitations
    LSTM Autoencoder 2019 Reconstruct normal patterns Simple, well-understood Limited long-range context
    GDN 2021 Graph-based inter-metric modeling Catches correlation anomalies Complex graph construction
    Anomaly Transformer 2022 Attention association discrepancy Strong benchmark results Computationally expensive
    TimesNet 2023 1D→2D transformation + CNN Multi-task capable Assumes periodic structure
    DCdetector 2023 Dual-attention contrastive learning SOTA on multiple benchmarks Requires careful tuning

     

    Foundation Models for Time Series: The 2025-2026 Frontier

    The most consequential development in time-series analysis over the past two years has been the emergence of foundation models—large, pre-trained models capable of performing time-series tasks, including anomaly detection, on data they have never previously seen, without task-specific training. This represents the same paradigm shift that GPT introduced to language and CLIP introduced to vision: train once on substantial diverse data, then apply to arbitrary downstream tasks via fine-tuning or zero-shot inference.

    TimesFM (Google, 2024)

    TimesFM (Time Series Foundation Model), developed by Google Research, was pre-trained on approximately 100 billion time points from diverse sources, including financial markets, weather stations, energy consumption, web traffic, and synthetic data. At 200 million parameters, TimesFM is designed as a decoder-only transformer that generates point forecasts. Anomaly detection is achieved by flagging observations that deviate significantly from the model’s zero-shot forecast.

    TimesFM’s notable property is that it produces competitive forecasts, and therefore competitive anomaly detection, without exposure to the user’s specific data during training. A practitioner provides a time series, the model generates a forecast based on patterns learned from 100 billion diverse time points, and the actuals are compared against the forecasts. This zero-shot capability removes the need for per-dataset model training and substantially reduces time-to-deployment for new monitoring use cases.

    Chronos (Amazon, 2024)

    Chronos (Ansari et al., 2024), from Amazon, takes an innovative approach: it tokenises time-series values into discrete bins (analogous to how language models tokenise words) and then applies a standard language model architecture (T5) to the tokenised sequence. This allows Chronos to use production-proven language model architectures and training procedures for time-series tasks.

    Chronos offers multiple model sizes (Mini: 20M, Small: 46M, Base: 200M, Large: 710M parameters) and performs well in zero-shot evaluations. For anomaly detection, the approach is forecast-based: Chronos generates probabilistic forecasts, and observations falling outside the prediction intervals are flagged as anomalous.

    import torch
    from chronos import ChronosPipeline
    
    # Load pre-trained Chronos model
    pipeline = ChronosPipeline.from_pretrained(
        "amazon/chronos-t5-base",
        device_map="auto",
        torch_dtype=torch.float32,
    )
    
    # Generate probabilistic forecast (zero-shot — no training needed)
    context = torch.tensor(historical_data)  # Your time series
    forecast = pipeline.predict(
        context,
        prediction_length=24,  # Forecast next 24 steps
        num_samples=100,       # Generate 100 forecast samples
    )
    
    # Anomaly detection via prediction intervals
    median_forecast = forecast.median(dim=1).values
    lower_bound = forecast.quantile(0.025, dim=1).values  # 2.5th percentile
    upper_bound = forecast.quantile(0.975, dim=1).values   # 97.5th percentile
    
    # Points outside the 95% prediction interval are anomalies
    anomalies = (actual_values < lower_bound) | (actual_values > upper_bound)
    

    MOMENT (CMU, 2024)

    MOMENT (Goswami et al., 2024)—Multi-task Open-source pre-trained Model for Every Time series—is a family of models specifically designed for multiple time-series tasks, including anomaly detection, classification, forecasting, and imputation. Unlike TimesFM and Chronos, which approach anomaly detection indirectly through forecasting, MOMENT is explicitly trained with an anomaly detection objective during pre-training.

    MOMENT uses a masked reconstruction objective. During pre-training, random patches of the time series are masked, and the model learns to reconstruct them. For anomaly detection, the reconstruction error at each time step serves as the anomaly score. Observations that the model finds difficult to reconstruct from context—because they deviate from patterns learned across its substantial pre-training dataset—receive high anomaly scores.

    MOMENT is open source, available on Hugging Face, and supports fine-tuning for domain-specific applications. Its anomaly detection performance is competitive with specialised models trained on the target dataset, despite MOMENT requiring no task-specific training.

    Timer and TimeGPT: Commercial and Research Alternatives

    TimeGPT (Nixtla, 2024) is a commercially available foundation model with an API-based interface. Users send time-series data to the API and receive forecasts and anomaly scores without managing any model infrastructure. TimeGPT is attractive for teams that wish to access foundation model capabilities without the complexity of model deployment, though it requires sending data to an external service, which is unacceptable for sensitive applications.

    Timer (Liu et al., 2024), from Tsinghua University, is a generative pre-trained transformer for time series that unifies multiple analytical tasks. It uses an autoregressive next-token prediction objective (analogous to GPT) on tokenised time-series data, and can perform anomaly detection, forecasting, and imputation in a single framework.

    Foundation Model Origin Parameters Open Source Anomaly Approach Key Advantage
    TimesFM Google 200M Yes Forecast-based substantial pre-training data (100B points)
    Chronos Amazon 20M-710M Yes Probabilistic forecast Multiple sizes, LLM architecture
    MOMENT CMU 40M-385M Yes Masked reconstruction Explicit anomaly detection objective
    TimeGPT Nixtla Undisclosed No (API) Forecast-based Zero infrastructure, API-ready
    Timer Tsinghua 67M Yes Autoregressive GPT-style unified framework

     

    Model Category Comparison: Statistical vs ML vs Deep Learning Statistical Methods ML Methods Deep Learning Examples STL, ARIMA, ETS Examples Isolation Forest, Matrix Profile Examples LSTM AE, GDN, Anomaly Transformer Training Data Minimal—days of history Training Data Moderate—weeks of history Training Data Large, months of normal data Multivariate Limited (univariate focus) Multivariate Yes (feature engineering) Multivariate Native (learns correlations) Accuracy good for simple series Accuracy strong baseline Accuracy best on complex data

    Tip: Foundation models perform particularly well when anomaly detection must be deployed quickly on new, unseen time series without first collecting training data. If abundant historical data with labelled anomalies is available for the relevant domain, a fine-tuned specialised model (such as Anomaly Transformer or DCdetector) may still outperform zero-shot foundation models. The appropriate choice depends on whether the principal constraint is labelled-data availability or model performance ceiling.

    Benchmarks and Real-World Performance

    The academic community evaluates anomaly detection models on several standard benchmark datasets. Understanding these benchmarks, and their limitations, helps calibrate expectations for real-world performance.

    Dataset Domain Dimensions Anomaly % Key Challenge
    SMD Server Machines 38 ~4.2% Multi-entity, diverse patterns
    MSL NASA Spacecraft 55 ~10.7% Telemetry with complex physics
    SMAP NASA Soil Moisture 25 ~13.1% Sensor noise, gradual drifts
    SWaT Water Treatment Plant 51 ~12.1% Cyber-physical attacks, subtle
    PSM eBay Server Metrics 25 ~27.8% High anomaly rate, noisy labels

     

    Caution: A 2023 paper by Kim et al. (“Towards a Rigorous Evaluation of Time-Series Anomaly Detection”) demonstrated that many published benchmark results are inflated by methodology issues, particularly the use of point-adjust (PA) metrics that credit models for detecting any point within an anomaly segment, even when the detection is delayed. Under stricter metrics, the performance gap between methods narrows considerably, and some classical methods perform comparably with deep models. Models should always be evaluated on the practitioner’s own data using metrics that reflect operational requirements, including detection latency and the false positive rate at a target recall.

    Practical Guide: Choosing the Right Model for the Problem

    With so many available models, selection can be challenging. The following decision framework draws on real-world constraints:

    Decision Framework

    Is labelled anomaly data available?

    • Yes (100 or more labelled anomalies): Fine-tune a supervised or semi-supervised model. Consider fine-tuning MOMENT or training DCdetector with the labels guiding threshold selection.
    • No: Use unsupervised methods. Proceed to the next question.

    Is the deployment new, with no historical training data?

    • Yes: Use a foundation model (Chronos, TimesFM, or MOMENT) in zero-shot mode. Competitive detection is available immediately without training.
    • No (ample historical data): Train a specialised model for best performance. Proceed to the next question.

    Is the problem univariate or multivariate?

    • Univariate (single metric): STL decomposition with thresholding is difficult to beat for simplicity and interpretability. For higher accuracy, use Matrix Profile or an LSTM autoencoder.
    • Multivariate (many correlated metrics): Use Anomaly Transformer, DCdetector, or GDN to capture inter-metric correlations.

    What are the latency requirements?

    • Real time (sub-second): Avoid transformer models at inference. Use Isolation Forest, streaming Matrix Profile (via STUMPY), or lightweight LSTM models.
    • Near real time (seconds to minutes): Any model is feasible with appropriate infrastructure.
    • Batch (hourly or daily): Prioritise accuracy over speed. Use the most capable model available.

    Implementation: Building an Anomaly Detection Pipeline

    A production anomaly detection system involves more than the model alone. The full pipeline architecture is as follows:

    Anomaly Detection Pipeline Data Ingestion metrics / logs Pre- processing normalize, fill gaps Detection Model Chronos / MOMENT Anomaly Score recon. error / deviation Threshold Decision calibrate on normal data Alert & Remediate PagerDuty / auto-rollback operator feedback loop (fine-tuning)

    # Complete anomaly detection pipeline with Chronos
    import torch
    import numpy as np
    from chronos import ChronosPipeline
    from dataclasses import dataclass
    from typing import Optional
    
    @dataclass
    class AnomalyResult:
        timestamp: str
        value: float
        expected: float
        lower_bound: float
        upper_bound: float
        anomaly_score: float
        is_anomaly: bool
    
    class TimeSeriesAnomalyDetector:
        def __init__(
            self,
            model_name: str = "amazon/chronos-t5-small",
            context_length: int = 512,
            prediction_length: int = 1,
            confidence_level: float = 0.95,
        ):
            self.pipeline = ChronosPipeline.from_pretrained(
                model_name,
                device_map="auto",
                torch_dtype=torch.float32,
            )
            self.context_length = context_length
            self.prediction_length = prediction_length
            self.alpha = 1 - confidence_level
    
        def detect(
            self,
            history: np.ndarray,
            actual_value: float,
            timestamp: str,
        ) -> AnomalyResult:
            """Detect if actual_value is anomalous given history."""
            # Use last context_length points
            context = torch.tensor(
                history[-self.context_length:]
            ).unsqueeze(0).float()
    
            # Generate probabilistic forecast
            forecast = self.pipeline.predict(
                context,
                prediction_length=self.prediction_length,
                num_samples=200,
            )
    
            # Extract prediction intervals
            median = forecast.median(dim=1).values[0, 0].item()
            lower = forecast.quantile(
                self.alpha / 2, dim=1
            ).values[0, 0].item()
            upper = forecast.quantile(
                1 - self.alpha / 2, dim=1
            ).values[0, 0].item()
    
            # Calculate anomaly score (normalized deviation)
            interval_width = upper - lower
            if interval_width > 0:
                score = abs(actual_value - median) / interval_width
            else:
                score = abs(actual_value - median)
    
            is_anomaly = actual_value < lower or actual_value > upper
    
            return AnomalyResult(
                timestamp=timestamp,
                value=actual_value,
                expected=median,
                lower_bound=lower,
                upper_bound=upper,
                anomaly_score=score,
                is_anomaly=is_anomaly,
            )
    
    # Usage
    detector = TimeSeriesAnomalyDetector()
    result = detector.detect(
        history=cpu_usage_last_7_days,
        actual_value=current_cpu_reading,
        timestamp="2026-04-03T08:15:00Z",
    )
    
    if result.is_anomaly:
        print(f"ANOMALY at {result.timestamp}: "
              f"value={result.value:.1f}, "
              f"expected={result.expected:.1f} "
              f"[{result.lower_bound:.1f}, {result.upper_bound:.1f}]")
    

    Pipeline components beyond the model itself include:

    • Data preprocessing. Handle missing values (forward-fill or interpolation), normalise scales across metrics, and align timestamps across data sources.
    • Threshold calibration. Use a validation period of known-normal data to calibrate anomaly thresholds. A threshold set too low produces a flood of false positives; one set too high misses real incidents.
    • Suppression and deduplication. A single incident may trigger dozens of anomaly alerts across correlated metrics. Group alerts by time window and root cause to avoid alert fatigue.
    • Feedback loop. Operators who acknowledge or dismiss alerts provide implicit labels. This data should be fed back into the model as a fine-tuning signal to improve detection over time.
    • Seasonal awareness. Explicitly model known business cycles (daily patterns, weekend effects, holiday traffic shifts) to reduce false positives during expected but unusual periods.

    Where the Field Is Heading

    Time-series anomaly detection is at an inflection point. The convergence of foundation models, transformer architectures, and practical tooling is making it possible to deploy sophisticated anomaly detection systems with substantially less effort than was the case even two years ago. Whereas a 2022 deployment required collecting domain-specific training data, training a specialised model, and calibrating thresholds through iterative experimentation, a 2026 deployment can begin with a zero-shot foundation model that delivers competitive performance from day one and improves with domain-specific fine-tuning.

    Several trends will shape the next two to three years:

    Multimodal foundation models that jointly reason over time-series metrics, log messages, and trace data are emerging from research laboratories. An anomaly detection system that can correlate a latency spike with a specific error message in the application logs and a deployment event in the change management system would substantially reduce mean time to diagnosis, not merely detection.

    LLM-augmented anomaly explanation represents a further frontier. Current systems indicate that something is anomalous but rarely explain why. Integrating LLMs that can explain anomaly detections in natural language (“CPU spiked to 95% at 3:14 PM, coinciding with a deployment of version 2.4.1 to the payment service; the historical pattern suggests a connection between this deployment and similar spikes”) would close the gap between detection and remediation.

    Edge deployment of lightweight anomaly detection models is becoming practical as foundation model distillation techniques improve. Running a compact anomaly detector directly on IoT devices, industrial sensors, or network routers, without round-tripping data to a cloud service, enables real-time detection with lower latency and improved data privacy.

    The field has moved from the question “can anomalies be detected automatically?” (yes, reliably, since the late 2010s) to “can anomalies be detected without per-dataset training?” (yes, with foundation models, since 2024). The current frontier is whether anomalies can be detected, explained, and accompanied by suggested remediation, all in real time. That question is being actively answered, and the pace of progress suggests it will not remain open for long.


    References

    • Xu, Jiehui, et al. “Anomaly Transformer: Time Series Anomaly Detection with Association Discrepancy.” ICLR 2022.
    • Yang, Yiyuan, et al. “DCdetector: Dual Attention Contrastive Representation Learning for Time Series Anomaly Detection.” ICML 2023.
    • Wu, Haixu, et al. “TimesNet: Temporal 2D-Variation Modeling for General Time Series Analysis.” ICLR 2023.
    • Ansari, Abdul Fatir, et al. “Chronos: Learning the Language of Time Series.” arXiv:2403.07815, 2024.
    • Das, Abhimanyu, et al. “A Decoder-Only Foundation Model for Time-Series Forecasting.” (TimesFM) ICML 2024.
    • Goswami, Mononito, et al. “MOMENT: A Family of Open Time-Series Foundation Models.” ICML 2024.
    • Deng, Ailin, and Bryan Hooi. “Graph Neural Network-Based Anomaly Detection in Multivariate Time Series.” AAAI 2021.
    • Audibert, Julien, et al. “USAD: UnSupervised Anomaly Detection on Multivariate Time Series.” KDD 2020.
    • Kim, Siwon, et al. “Towards a Rigorous Evaluation of Time-Series Anomaly Detection.” AAAI 2023.
    • Liu, Fei Tony, Kai Ming Ting, and Zhi-Hua Zhou. “Isolation Forest.” ICDM 2008.
    • Yeh, Chin-Chia Michael, et al. “Matrix Profile I: All Pairs Similarity Joins for Time Series.” ICDM 2016.
    • Time-Series-Library (THU)—Unified framework for time-series models including anomaly detection
    • Amazon Chronos GitHub Repository
    • MOMENT GitHub Repository
  • Docker Containers Explained: From Development to Production

    Summary

    What this post covers: A practical guide that progresses from the rationale for Docker through its core concepts (images, containers, registries), Dockerfile authoring, Compose-based multi-service stacks, networking and volumes, and the production hardening that distinguishes a functioning container from a deployable one.

    Key insights:

    • Docker’s principal contribution is treating the runtime environment itself as part of the shipped artifact, which eliminates the entire class of “works on my machine” defects at their source rather than mitigating them downstream.
    • Containers share the host kernel and virtualize only the operating system, which is why they start in milliseconds with megabytes of overhead while virtual machines require minutes and gigabytes. This performance gap is what enables microservices, ephemeral CI environments, and immutable deployments.
    • Containers are deliberately ephemeral. Persistent state must reside in volumes or external databases, and any data written to a container’s writable layer is lost when the container stops.
    • Production Docker requires deliberate adjustments from development defaults. Multi-stage builds for small images, non-root users, pinned versions, health checks, resource limits, and structured logging are not optional.
    • In the majority of outages, docker logs reveals the actual cause on the first line. Missing environment variables and unreachable dependencies account for most “container exits immediately” incidents.

    Main topics: Why Docker Changed Software Development Forever, Core Concepts: Images, Containers, and Registries, Writing a First Dockerfile, Docker Compose: Multi-Container Applications, Networking: How Containers Communicate, Persistent Data with Volumes, Production Best Practices: Adjustments for Live Environments, Common Patterns: Web App, API with Database, Worker Queue, Debugging Containers: Diagnosing Failures, From Development to Production: A Mental Model, References.

    In 2013, a developer named Solomon Hykes delivered a five-minute presentation at PyCon. He demonstrated a tool capable of packaging an application together with everything required to run it—libraries, configuration, runtime—into a portable unit that behaved identically on any Linux machine. The audience applauded politely. Docker was open-sourced two months later, and within five years it had become one of the most influential technologies in the history of software development.

    The problem Docker addressed had affected practitioners for as long as software has existed: the recurring observation that code which runs correctly on a developer’s laptop fails in staging, that applications which behave one way in staging behave differently in production, and that new engineers spend days configuring local environments that never quite replicate the cloud target. Entire categories of defects existed because the environments in which code executed differed in invisible and difficult-to-reproduce ways.

    Docker’s response was the container: an isolated, reproducible runtime environment that packages code and all its dependencies into a single artifact that behaves identically across hosts. A container built on a MacBook Pro will run identically on an Ubuntu server in AWS, on a Windows workstation, or on a Raspberry Pi running ARM Linux. Behavior, dependencies, and configuration remain constant across all targets.

    In 2026, Docker and container technology are no longer optional knowledge for professional developers; they are foundational. The remainder of this post proceeds from first principles to production-ready patterns, covering the concepts and commands required to use Docker in real projects rather than to understand it only abstractly. For a companion piece that explores container internals, virtual machines versus containers, and layer caching strategies in greater depth, see the Docker containers explained guide.

    Why Docker Changed Software Development Forever

    To understand why Docker matters, one must first understand what it replaced. Before containers, deploying software typically involved one of two approaches.

    Manual server configuration: An operator would connect to a server via SSH and install dependencies by hand, documenting the steps in a README and trusting that subsequent operators would follow them correctly. Engineers would later discover that production was running Python 3.8 while development was using Python 3.11, then spend days tracing the resulting behavioral differences. The approach was slow, error-prone, and impossible to scale.

    Virtual Machines (VMs): Virtual machines address the consistency problem by virtualizing the entire hardware stack. A complete operating system image is packaged and executed inside another operating system. However, virtual machines are heavyweight. A typical image is gigabytes in size and takes minutes to boot. Running fifty isolated services as separate virtual machines requires fifty copies of a full operating system and consumes substantial resources.

    Docker containers take a different approach: rather than virtualizing hardware, they virtualize the operating system. Containers share the host kernel but maintain isolated filesystems, processes, and network interfaces. The result is environments that are isolated like virtual machines yet lightweight like processes. A container starts in milliseconds rather than minutes and incurs overhead measured in megabytes rather than gigabytes.

    This performance profile enables patterns that were impractical with virtual machines: operating fifty isolated microservices on a single server, instantiating ephemeral test environments for every pull request, and deploying code updates by replacing containers rather than executing update scripts. These patterns are now industry standard, and Docker is the technology that made them practical. For example, event-driven architectures based on Apache Kafka for stream processing or Apache Flink for complex event processing rely heavily on containerized deployments to scale individual pipeline stages independently.

    Container vs Virtual Machine: Resource Layers Virtual Machines Physical Hardware Host Operating System Hypervisor Guest OS Libs / Bins App ~GB image · mins to boot Guest OS Libs / Bins App ~GB image · mins to boot Docker Containers Physical Hardware Host OS Kernel (shared) Docker Engine Libs / Bins App ~MB image · ms to start Libs / Bins App ~MB image · ms to start

    Key Takeaway: Docker resolves the “works on my machine” problem by making the machine itself part of the shipped artifact. The container image is simultaneously the packaging mechanism and the guarantee of consistency. The deliverable is not code dispatched in the hope that the destination environment is compatible, but the environment itself.

    Core Concepts: Images, Containers, and Registries

    Docker’s conceptual model rests on three core entities. Conflating them is the most common source of error among newcomers, so each requires precise definition.

    Docker Images: The Blueprint

    A Docker image is a read-only template containing everything required to run an application: the operating system filesystem, application code, libraries, environment variables, and startup commands. An image is built once and can be instantiated as many containers. An image is analogous to a class definition in object-oriented programming—a blueprint rather than the entity itself.

    Images are constructed in layers. Each instruction in a Dockerfile produces a new layer. Layers are cached and reused, so if application code changes but dependencies do not, Docker rebuilds only the modified layers. This layered cache is the reason Docker builds become fast after the initial one.

    Docker Containers: The Running Instance

    A container is a running instance of an image. When an image is executed, Docker creates a writable layer above the image’s read-only layers and starts the specified process. The container possesses an isolated filesystem, network interface, and process namespace. Multiple containers can run concurrently from the same image, each maintaining its own writable state.

    An important property: containers are ephemeral by design. When a container stops, any data written to its filesystem is lost unless stored in a volume, which is discussed later. This ephemerality is a deliberate property rather than a defect. It allows containers to be destroyed and recreated without concern for accumulated state. Persistent data belongs in volumes, and application state belongs in external databases.

    Docker Registries: The Distribution Layer

    A registry is a storage system for Docker images. Docker Hub is the default public registry, hosting hundreds of thousands of community and official images, including Ubuntu, Node.js, PostgreSQL, Redis, and nginx. Private registries such as AWS ECR, Google Artifact Registry, and GitHub Container Registry store proprietary images within an organization’s own infrastructure.

    The workflow is straightforward: an image is built locally, pushed to a registry, and pulled from that registry on any machine that needs to run it. This is how code travels from a developer’s laptop to a production server without manual file copying or SSH-based deployment scripts.

    Docker Architecture: How the Pieces Connect Docker CLI docker run / build REST API Docker Daemon dockerd manages lifecycle Images read-only layers cached + reused run Containers running process isolated + ephemeral Registry Docker Hub ECR · GHCR push / pull Developer interface Orchestration engine Immutable blueprints Live processes Image store

    Writing a First Dockerfile

    A Dockerfile is a text file containing instructions for building a Docker image, with each instruction producing a layer. The following example builds a Python web application image step by step using FastAPI, which is examined in detail in the companion FastAPI guide.

    Docker Development Workflow: Code to Registry Dockerfile FROM · RUN COPY · CMD build Build layer cache fast rebuilds Image immutable tagged artifact run Container live process isolated env push Registry Docker Hub ECR · GHCR pull Production Server same image identical behavior Every environment, dev, staging, production—runs the same image. No more “works on my machine.”

    # Start from an official Python runtime as the base image
    FROM python:3.12-slim
    
    # Set the working directory inside the container
    WORKDIR /app
    
    # Copy dependency files first (for better layer caching)
    COPY requirements.txt .
    
    # Install Python dependencies
    RUN pip install --no-cache-dir -r requirements.txt
    
    # Copy the rest of the application code
    COPY . .
    
    # Create a non-root user for security
    RUN useradd --create-home appuser && chown -R appuser /app
    USER appuser
    
    # Tell Docker what port the app uses (documentation only)
    EXPOSE 8000
    
    # Command to run when container starts
    CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
    

    Several decisions embedded in this Dockerfile are important for production use.

    python:3.12-slim rather than python:3.12: The slim variant omits documentation, test files, and other non-essential components, reducing image size from approximately 900 MB to roughly 130 MB. Smaller images build faster, transfer faster, and present a smaller attack surface. For practitioners considering a compiled language to produce leaner containers, the Python and Rust comparison examines how Rust’s static binaries can yield single-digit-megabyte images.

    Copying requirements.txt before the application code: Docker rebuilds only the layers that have changed and any layers that follow them. Copying dependencies before source code allows the expensive pip install step to remain cached as long as requirements.txt is unchanged, even when application code changes. The result is substantially faster iterative builds.

    Running as a non-root user: Processes in containers run as root by default. This poses a security risk: an attacker who exploits an application vulnerability obtains root access inside the container. Creating a non-root user and switching to it is a low-effort improvement with meaningful security benefit.

    The image can then be built and executed as follows.

    # Build the image, tagging it as "myapp:latest"
    docker build -t myapp:latest .
    
    # Run the container, mapping host port 8080 to container port 8000
    docker run -p 8080:8000 myapp:latest
    
    # Run in detached mode (background)
    docker run -d -p 8080:8000 --name myapp myapp:latest
    
    # View running containers
    docker ps
    
    # View container logs
    docker logs myapp
    
    # Stop the container
    docker stop myapp
    

    Docker Compose: Multi-Container Applications

    Real applications rarely run in isolation. A typical web application requires a database, a cache, possibly a background worker, and sometimes a reverse proxy. Running and connecting such services manually with docker run commands becomes unmanageable. Docker Compose addresses this by defining and running multi-container applications from a single YAML configuration file.

    The following docker-compose.yml defines a FastAPI application paired with PostgreSQL and Redis.

    services:
      # The web application
      web:
        build: .
        ports:
          - "8000:8000"
        environment:
          DATABASE_URL: postgresql://postgres:secret@db:5432/appdb
          REDIS_URL: redis://redis:6379/0
        depends_on:
          db:
            condition: service_healthy
          redis:
            condition: service_started
        volumes:
          - ./src:/app/src  # Mount source for hot reload in development
    
      # PostgreSQL database
      db:
        image: postgres:16-alpine
        environment:
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: secret
          POSTGRES_DB: appdb
        volumes:
          - postgres_data:/var/lib/postgresql/data  # Persist data
        healthcheck:
          test: ["CMD-SHELL", "pg_isready -U postgres"]
          interval: 5s
          timeout: 5s
          retries: 5
    
      # Redis cache
      redis:
        image: redis:7-alpine
        volumes:
          - redis_data:/data
    
    # Named volumes persist data between container restarts
    volumes:
      postgres_data:
      redis_data:
    

    Several patterns in this configuration warrant attention.

    Service discovery by name: The web service connects to the database using db as the hostname, visible in DATABASE_URL: postgresql://...@db:5432/.... Docker Compose creates an internal network on which each service is reachable by its service name, removing the need for hardcoded IP addresses.

    Health checks with depends_on: Declaring depends_on: db alone only waits for the database container to start, not for PostgreSQL to be ready to accept connections. Combining condition: service_healthy with a health check ensures the web service does not start until the database is actually responsive.

    Volume mounts for development: Mounting ./src:/app/src ensures that source code changes on the host machine are immediately reflected inside the container, enabling hot reload without rebuilding the image for every change.

    # Start all services (detached)
    docker compose up -d
    
    # View logs from all services
    docker compose logs -f
    
    # View logs from a specific service
    docker compose logs -f web
    
    # Stop all services
    docker compose down
    
    # Stop and remove volumes (WARNING: deletes data)
    docker compose down -v
    
    # Rebuild images after Dockerfile changes
    docker compose up -d --build
    
    # Run a one-off command in a service container
    docker compose exec web python manage.py migrate
    

    Networking: How Containers Communicate

    Docker’s networking model rests on a few concepts that frequently cause confusion among developers encountering container networking for the first time.

    Each container has its own network namespace. Inside a container, localhost refers to the container itself rather than the host machine. This often surprises developers: a web server inside a container cannot connect to a database running on the host using localhost:5432 because the database is not “local” from the container’s perspective.

    Docker Compose creates a default network. All services declared in a docker-compose.yml file are automatically connected to a shared bridge network on which services reach one another by service name. The web service connects to db using the hostname db, not localhost.

    Port publishing exposes containers to the host. The ports: - "8000:8000" syntax publishes container port 8000 on host port 8000. Without this directive, the service is reachable only from within the Docker network and not from a browser on the host machine.

    Internal services should not publish ports in production. A database container does not need to be reachable from outside Docker in production; only the web application requires external access. Omitting port publishing for internal services such as databases, caches, and workers substantially reduces the attack surface.

    Persistent Data with Volumes

    Containers are ephemeral: when a container is removed, its writable layer disappears, and any data written directly to the container filesystem is lost. Databases, file uploads, configuration, and any other data that must survive container restarts require volumes.

    Docker provides two persistence mechanisms.

    Named volumes are managed by Docker and stored in its storage area on the host, typically at /var/lib/docker/volumes/. They are the recommended mechanism for persisting database data because Docker manages their lifecycle independently of any particular container. In the Compose example above, postgres_data and redis_data are named volumes.

    Bind mounts map a specific directory on the host machine to a path inside the container. The ./src:/app/src mount in the development configuration is a bind mount. Changes on the host are immediately visible inside the container. Bind mounts are well suited to development because they enable live code reload, but they are less appropriate for production because they introduce a dependency on the host filesystem structure.

    # List all volumes
    docker volume ls
    
    # Inspect a named volume (shows where data is stored on host)
    docker volume inspect myapp_postgres_data
    
    # Back up a named volume
    docker run --rm \
      -v myapp_postgres_data:/data \
      -v $(pwd):/backup \
      alpine tar czf /backup/postgres_backup.tar.gz /data
    
    # Remove unused volumes (careful — this deletes data!)
    docker volume prune
    

    Production Best Practices: Adjustments for Live Environments

    A Docker configuration that performs well in development can still fail in production in unexpected ways. The gap between “the application runs in Docker” and “the application runs reliably in production Docker” is bridged by several important practices.

    Multi-Stage Builds: Separating Build from Runtime

    Many applications require build tools that are unnecessary at runtime, including compilers, test frameworks, and build system dependencies. Multi-stage builds allow a heavy build environment to produce artifacts that are then copied into a minimal runtime image.

    # Stage 1: Build stage (can be large)
    FROM node:20 AS builder
    WORKDIR /app
    COPY package*.json ./
    RUN npm ci
    COPY . .
    RUN npm run build  # Produces /app/dist
    
    # Stage 2: Production runtime (minimal)
    FROM node:20-alpine AS production
    WORKDIR /app
    COPY package*.json ./
    RUN npm ci --omit=dev  # Only production dependencies
    COPY --from=builder /app/dist ./dist  # Copy only build output
    USER node
    EXPOSE 3000
    CMD ["node", "dist/server.js"]
    

    The final image contains only the Node.js runtime, production dependencies, and compiled output, with no TypeScript compiler, development dependencies, or source files. The reduction in image size can move from more than 1 GB to under 200 MB.

    Avoiding Secrets in Images

    One of the most common security errors, and a violation of clean code principles, is embedding credentials, API keys, or passwords in a Dockerfile or in the image itself. Docker image layers are readable by anyone with access to the image. Even if the secret is added in one layer and removed in another, it remains accessible in the intermediate layer’s history.

    # WRONG: Secret baked into image
    ENV API_KEY=sk-super-secret-key-12345
    
    # RIGHT: Pass secrets at runtime as environment variables
    # In docker run:
    docker run -e API_KEY="${API_KEY}" myapp
    
    # In Docker Compose with an .env file:
    # .env file (never commit this to git):
    # API_KEY=sk-super-secret-key-12345
    
    # docker-compose.yml:
    # environment:
    #   API_KEY: ${API_KEY}  # Reads from .env file
    

    Container Health Checks in Production

    In production environments that employ container orchestration such as Kubernetes, Docker Swarm, or AWS ECS, the orchestrator requires a mechanism to determine container health. Without a health check, the orchestrator assumes that the container is healthy as long as the process is running, even when the application returns HTTP 500 errors for every request.

    HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
      CMD curl -f http://localhost:8000/health || exit 1
    

    The application should expose a /health endpoint that returns HTTP 200 when it is ready to serve requests and can reach its dependencies. The orchestrator will restart unhealthy containers and direct traffic away from them.

    Resource Limits

    Without resource limits, a misbehaving container can consume all available memory or CPU on a host, starving other services. Memory and CPU limits should always be configured in production.

    services:
      web:
        image: myapp:latest
        deploy:
          resources:
            limits:
              memory: 512M
              cpus: "1.0"
            reservations:
              memory: 256M
              cpus: "0.5"
    

    Common Patterns: Web App, API with Database, Worker Queue

    Pattern 1: Web App with Nginx Reverse Proxy

    It is standard practice in production to run a reverse proxy such as nginx or Caddy in front of the application. The proxy handles SSL termination, static file serving, request buffering, and load balancing, allowing the application server to focus on business logic.

    services:
      nginx:
        image: nginx:alpine
        ports:
          - "80:80"
          - "443:443"
        volumes:
          - ./nginx.conf:/etc/nginx/conf.d/default.conf
          - ./certs:/etc/nginx/certs
        depends_on:
          - web
    
      web:
        build: .
        # Note: NO ports published — only nginx reaches this container
        expose:
          - "8000"
    

    Pattern 2: Background Worker with Celery and Redis

    Long-running tasks such as sending emails, processing images, or generating reports should not block HTTP request handlers. The standard pattern queues these tasks and processes them asynchronously through a worker process.

    services:
      web:
        build: .
        command: uvicorn main:app --host 0.0.0.0 --port 8000
    
      worker:
        build: .  # Same image, different command
        command: celery -A tasks worker --loglevel=info
        depends_on:
          - redis
          - db
    
      redis:
        image: redis:7-alpine
    
      db:
        image: postgres:16-alpine
    

    The web and worker services share the same Docker image but execute different commands. This is a common pattern for Python applications: one image, multiple process types, all defined in a single Compose file.

    Debugging Containers: Diagnosing Failures

    Every Docker practitioner accumulates a set of debugging commands. The following are the most frequently used.

    # Open an interactive shell inside a running container
    docker exec -it container_name bash
    # or if bash isn't available (Alpine-based images):
    docker exec -it container_name sh
    
    # Inspect container details (env vars, mounts, network settings)
    docker inspect container_name
    
    # View real-time resource usage (CPU, memory, network I/O)
    docker stats
    
    # Check what files are different from the base image
    docker diff container_name
    
    # Start a stopped container to investigate its state
    docker start -ai container_name
    
    # Run a debugging container with access to all host namespaces
    docker run -it --rm --privileged --pid=host debian nsenter -t 1 -m -u -n -i sh
    
    # Build with verbose output (shows each layer build step)
    docker build --progress=plain .
    
    # Check why a layer is cache-busting (useful for slow builds)
    docker history myapp:latest
    

    The most common debugging scenario is a container that exits immediately after starting. The remedy is to run it interactively in order to surface the error.

    # Override the CMD to drop into a shell instead of running the app
    docker run -it --rm myapp:latest bash
    
    # Or check the logs of an exited container
    docker logs container_name
    
    Tip: The most common cause of “container exits immediately” is an application crash on startup, a missing environment variable, an unreachable database, or a configuration error. Always run docker logs container_name first. The crash output is almost always present and identifies the precise failure.

    From Development to Production: A Mental Model

    Docker’s value lies not in any single feature but in the consistency it establishes across the entire software delivery lifecycle. The same image that runs on a developer’s laptop is the image that is tested in continuous integration and deployed to production. The environment, comprising the operating system, libraries, and configuration structure, is defined once in a Dockerfile and reproduced exactly across all targets.

    The conceptual shift that Docker enables is the treatment of infrastructure as code. The Dockerfile is a precise, version-controlled specification of the application’s runtime environment. The docker-compose.yml is a precise, version-controlled specification of how services connect. Both reside in the repository, are reviewed in pull requests in accordance with Git and GitHub best practices, and are reproduced identically by any developer on the team within minutes through docker compose up.

    This consistency eliminates entire categories of defects, simplifies onboarding considerably, and renders the deployment pipeline reliable in ways that manual server configuration could not achieve. These factors explain why Docker adoption progressed from zero to ubiquitous in under a decade. The tool addressed real problems that developers encountered daily, and the developer experience was favorable.

    The path from this point to production-ready containers is straightforward: learn the Dockerfile instructions, understand Compose networking, master the debugging commands, and apply the production best practices outlined above. For a more detailed examination of container internals, virtual machine comparisons, and image optimization strategies, consult the companion Docker containers explained from development to production guide. The concepts are few and the practical return is substantial. Starting with a single application and containerizing it is the most direct way to understand why Solomon Hykes’ five-minute PyCon demonstration influenced an industry.


    References

  • Python vs Rust: Performance, Safety, and When to Use Each

    Summary

    What this post covers: A measured, decision-framework comparison of Python and Rust, examining where each language genuinely excels in performance, safety, ecosystem, learning curve and career impact, together with the methods for combining the two via PyO3.

    Key insights:

    • “Python vs Rust” is the wrong question. The correct one concerns which constraint dominates the problem: developer time (Python), runtime performance or memory footprint (Rust), or compile-time safety guarantees (Rust).
    • Rust runs 10 to 100 times faster than pure Python on CPU-bound code, but for data and ML workloads the gap narrows substantially once Python delegates to NumPy and PyTorch C and CUDA backends. The “two-language pattern” therefore remains highly competitive.
    • Rust’s borrow checker is what genuinely distinguishes the language. It eliminates use-after-free errors, data races and null-pointer dereferences at compile time, replacing entire categories of production outages.
    • The most rapidly growing pattern in 2026 is Python plus Rust hybrids: write the performance-critical 5 percent in Rust, expose it via PyO3 or maturin, and retain orchestration in Python. Polars, Pydantic v2 and Ruff have demonstrated the dominance of this model.
    • For careers, Python remains the broadest market (data, ML, web), but Rust commands premium salaries in systems, infrastructure, blockchain and, increasingly, AI inference engines. Learning both is increasingly the high-leverage choice.

    Main topics: The Real Question Is Not “Which Is Better?”, Python: Where It Excels and Why, Rust: A Modern Systems Programming Language, Performance: What the Benchmarks Show and Mask, Memory Safety: Why Rust’s Approach Matters, The Learning Curve: A Measured Assessment, Real-World Use Cases: Where Each Language Predominates, Python + Rust: A Combined Approach, Career Impact: What These Languages Mean for the Job Market, The Decision Framework, References.

    In 2006, the programmer Graydon Hoare was confronted with an unsettling event. The elevator in his apartment building had just crashed because the software controlling its door contained a memory bug. The fault was neither a logic error nor a missing feature, but a memory bug, the same class of error that has produced buffer overflows, security vulnerabilities and crashes since the early days of systems programming. Hoare, an employee at Mozilla, returned home and began sketching a programming language that would render such errors impossible. He called it Rust.

    In 1991, the Dutch programmer Guido van Rossum released a language he had been developing as a hobby project, intended to make programming more approachable, more readable and more human. He named it after Monty Python’s Flying Circus. He could not have anticipated that, three decades later, the language would underpin one of the fastest-growing fields in software, namely machine learning, would become the lingua franca of data science, and would consistently rank within the top three languages in developer surveys for “most used” and “most loved.”

    Python and Rust represent two of the most important languages in software development today, but they were created to address different problems. Python prioritises developer productivity and readability. Rust prioritises runtime performance and memory safety. Understanding which to use, and when, is among the most practically valuable decisions a developer can make in 2026.

    This article does not simply assert that “Python is slow and Rust is fast.” Such a summary is true but unhelpful. The discussion instead examines what each language genuinely excels at, where each struggles, how they can be combined, and how to make a decision suited to the reader’s specific work.

    The Real Question Is Not “Which Is Better?”

    Whenever the Python-versus-Rust debate surfaces on programming forums, it generates considerable heat and minimal light. Python devotees point to its ecosystem, readability and flexibility. Rust advocates cite its performance, safety guarantees and increasingly rich tooling. Both sides correctly identify their language’s strengths, and both miss the point.

    The correct framing is the following: what is the dominant constraint on the problem?

    If the dominant constraint is developer time, meaning that something must be built quickly, iterated upon rapidly, or used to experiment with different approaches, Python almost always wins. The combination of dynamic typing, an extensive standard library, a substantial third-party ecosystem (PyPI hosts more than 500,000 packages) and readable syntax means that Python developers write working code faster than in virtually any other language.

    If the dominant constraint is runtime performance or memory usage, for example a system that runs on embedded hardware, must process millions of operations per second, or must run in an environment in which garbage collection pauses are unacceptable, Rust is frequently the best available choice. It delivers C-level performance without C’s memory safety hazards.

    If the dominant constraint is reliability and safety, for example software in which crashes or security vulnerabilities have serious consequences (financial systems, medical devices, operating system components), Rust’s compile-time safety guarantees provide assurance that Python cannot match.

    The difficulty is that most developers do not frame the question in this way. They ask “which language should I learn?” or “which language should I use for this project?” without first identifying what actually constrains them. The following sections address that gap.

    Python: Where It Excels and Why

    Python’s principal advantage is its speed-to-insight ratio. From installing Python to writing a working web scraper, a data analysis script or a machine learning model, the time measured in developer hours is lower than for any comparable language. This is not accidental. Python was designed from the outset around the principle that “code is read more often than it is written,” and that philosophy informs every design decision.

    The Ecosystem That Transformed an Industry

    No language feature matters more for Python’s dominance in data science and machine learning than its ecosystem. NumPy, SciPy, Pandas and Matplotlib form the foundation of scientific computing in Python. TensorFlow and PyTorch, the two dominant deep learning frameworks, are Python-first. Scikit-learn, Hugging Face Transformers, LangChain and FastAPI have each fundamentally changed how their respective domains are practised, and all are Python.

    The critical observation about Python’s ecosystem is that the performance-critical code is not actually written in Python. NumPy’s array operations are implemented in C. PyTorch’s tensor operations run in C++ and CUDA. When a developer calls np.dot(a, b) to multiply two large matrices, Python syntax is used to invoke heavily optimised Fortran and C code. Python becomes the orchestration layer, the glue that connects high-performance components, rather than the performance layer itself. This architecture is sometimes termed the “two-language problem,” and it works remarkably well in practice.

    Python in Web Development

    Django, FastAPI and Flask have made Python a first-class web development language. FastAPI has in particular become widely used for building Python APIs, providing automatic OpenAPI documentation generation, native async support and performance approaching that of Node.js for I/O-bound workloads. For data-driven web applications, dashboards, ML-serving APIs and analytics tools, Python’s ability to connect business logic with data processing and a web interface in a single language is a genuine productivity advantage.

    # A complete working FastAPI endpoint in Python
    from fastapi import FastAPI
    from pydantic import BaseModel
    import numpy as np
    
    app = FastAPI()
    
    class PredictionRequest(BaseModel):
        features: list[float]
    
    @app.post("/predict")
    async def predict(request: PredictionRequest):
        # Imagine a trained model here
        score = np.mean(request.features) * 0.5
        return {"prediction": score, "confidence": 0.87}
    

    Twenty lines produce a complete, type-validated, auto-documented REST API endpoint. Python’s expressiveness per line of code is genuinely substantial.

    Where Python Struggles

    Python’s limitations are well known and warrant honest acknowledgement. The Global Interpreter Lock (GIL) means that Python cannot execute multiple threads in parallel across multiple CPU cores, a significant limitation for CPU-bound concurrent workloads. (Python 3.13 introduced an experimental “free-threaded” mode that removes the GIL, but ecosystem compatibility is still evolving.)

    Raw Python is slow for CPU-intensive operations. A Python loop processing millions of numbers will be 10 to 100 times slower than equivalent C or Rust code. This is usually mitigated by NumPy vectorisation, but it remains a real constraint for algorithms that do not vectorise easily.

    Python’s memory usage is high compared with lower-level languages. A Python list of integers uses approximately 28 bytes per integer, compared with 4 to 8 bytes in a compiled language. For systems processing large volumes of small data items, this overhead accumulates rapidly.

    Rust: A Modern Systems Programming Language

    Rust has achieved what was long considered improbable: a systems programming language that is both memory-safe and does not require a garbage collector. Understanding why this matters requires a brief detour into why memory management is difficult.

    In languages such as C and C++, the programmer is responsible for explicit allocation and deallocation of memory. This grants maximum control but creates an entire category of bugs, including use-after-free errors (using memory after it has been freed), double-free errors (freeing the same memory twice) and buffer overflows (writing beyond the end of an array). These bugs are the root cause of a substantial proportion of security vulnerabilities. The US National Security Agency has estimated that 70 percent of serious security vulnerabilities in recent years can be traced to memory safety issues.

    Languages such as Java, Python, Go and C# address this problem by adding a garbage collector, a runtime process that automatically identifies and frees unused memory. This eliminates memory bugs but introduces unpredictable pauses (the garbage collector must stop the world to collect garbage), higher memory overhead, and limits on deterministic performance, all problematic for real-time systems, operating system kernels and other low-level applications.

    Rust takes a third approach: it enforces memory safety at compile time, through a system called the borrow checker, with zero runtime overhead. If a Rust program compiles, the compiler has proven that it is free of memory safety bugs. No garbage collector is required. No runtime pauses occur. The result is safe, fast code.

    Rust’s Ownership System

    Rust’s memory model is built around three rules that the compiler enforces.

    1. Every value has exactly one owner.
    2. There can be any number of immutable references to a value, or exactly one mutable reference—but not both simultaneously.
    3. When the owner goes out of scope, the value is automatically freed.

    These rules sound straightforward but have substantial implications. They prevent data races, since two threads cannot mutate the same memory simultaneously. They prevent use-after-free bugs, since a reference cannot be used after its owner has freed the value. They prevent an entire class of concurrency bugs that affect C++ and Java programs. The compiler verifies all of this before the program executes.

    // Rust ownership example — this won't compile
    fn main() {
        let s1 = String::from("hello");
        let s2 = s1;  // s1's ownership moves to s2
    
        println!("{}", s1);  // Error: s1 was moved!
        // The compiler catches this at compile time, not runtime
    }
    
    // The correct way — explicitly clone when you need two owners
    fn main() {
        let s1 = String::from("hello");
        let s2 = s1.clone();  // Creates a deep copy
    
        println!("s1 = {}, s2 = {}", s1, s2);  // Works fine
    }
    

    Rust’s Growing Ecosystem

    Rust’s package manager, Cargo, is frequently cited as one of the best dependency management tools in any programming language. Through cargo build, cargo test, cargo doc and cargo fmt, the Rust toolchain handles the complete development workflow with minimal configuration. The crates.io package registry hosts more than 140,000 packages, and the quality and documentation standards are generally high.

    Major organisations have committed to Rust. The Linux kernel accepted Rust as its second implementation language in 2022, a historic milestone for a language that was then only seven years old. The Android team at Google rewrites security-sensitive components in Rust. Microsoft has been rewriting Windows components in Rust. The White House’s Office of the National Cyber Director explicitly recommended Rust as a memory-safe language for systems programming in its 2024 cybersecurity report.

    Performance: What the Benchmarks Show and Mask

    Benchmark comparisons between Python and Rust are striking. On CPU-intensive workloads, including the sorting of arrays, the computation of Fibonacci sequences and matrix operations in pure code, Rust is typically 10 to 100 times faster than pure Python. In some string processing benchmarks, Rust exceeds Python by 200 times or more.

    The figures can be misleading, however. Few real Python applications run in pure Python for their performance-critical parts. When a data scientist calls NumPy for array operations, the underlying computation runs at near-C speed. When a Python web server handles HTTP requests, I/O operations dominate runtime and the difference between Python and Rust at the application layer is minimal. When a PyTorch model trains on a GPU, the GPU compute time substantially exceeds any CPU overhead from the Python orchestration layer.

    Workload Type Pure Python vs. Rust Python+NumPy vs. Rust Practical Impact
    CPU-bound computation Python 50-200x slower 2-5x slower High for tight loops
    I/O-bound (web/network) ~2-5x slower ~2-5x slower Low (I/O dominates)
    ML training (GPU) Negligible overhead Negligible overhead None (GPU dominates)
    Memory usage 5-20x more memory 2-5x more memory High for constrained envs
    Startup time 100-500ms typical Same High for serverless/CLI
    Real-time latency GC pauses unpredictable Same Critical for real-time systems

     

    Python vs Rust—Feature Comparison Python Rust Score (out of 10) 10 8 6 4 2 Runtime Speed Memory Safety Ecosystem Size Ease of Learning Concur- rency 2 10 4 10 10 5 9 3 4 10 Scores are qualitative—relative strengths, not absolute benchmarks

    Memory Safety: Why Rust’s Approach Matters

    If performance were the sole consideration, C++ would be the obvious choice for high-performance software, since it is faster than Rust on certain benchmarks and has a substantially larger ecosystem. C++ code is, however, notoriously hazardous to write correctly. The Chrome browser team estimates that approximately 70 percent of Chrome’s serious security vulnerabilities are memory safety bugs in C++ code. Microsoft’s Security Response Center reports similar figures for Windows. These are not bugs introduced by careless programmers; they arise from expert C++ developers with years of experience, supported by code review, static analysis tools and extensive testing.

    Rust eliminates this entire class of vulnerability by construction. A Rust program that compiles cannot contain use-after-free bugs, buffer overflows from unchecked indexing (which produce panics rather than undefined behaviour), or data races. For this reason, the Linux kernel project, which had previously refused to admit any language other than C, made an exception for Rust. For the same reason, the Android team uses Rust for new security-sensitive code, and infrastructure that must be both fast and secure, including network proxies, cryptographic libraries and DNS servers, is increasingly written in Rust.

    Key Takeaway: Rust’s memory safety guarantees are not solely a matter of performance or correctness; they concern the economics of security. Every memory safety vulnerability in a production system carries a cost in incident response, patching and reputational damage. Rust trades upfront development friction (working with the borrow checker) for substantially lower downstream operational security risk.

    Memory Management: Python GC vs Rust Ownership Python (Garbage Collector) Heap Memory Object A ref count: 2 Object B ref count: 0 GC frees B Garbage Collector (runtime overhead) Periodic GC pauses; non-deterministic memory release; simpler to write vs Rust (Ownership System) Stack owner: s1 borrow: &s1 scope ends → auto freed Heap Data “hello, world” owned by s1 Freed exactly when owner leaves scope. Zero runtime GC. Compile-time enforced; zero overhead; no GC pauses; steeper to learn

    The Learning Curve: A Measured Assessment

    Rust is difficult to learn. Not in the sense that “the syntax is unusual” or “tutorials are scarce,” but in the sense that the compiler will reject code that any other language would accept, and the developer must fundamentally rethink data management to satisfy it. The borrow checker is intellectually demanding in a manner that has no direct analogue in Python, JavaScript, Java or most other languages that developers commonly know.

    Most developers report that learning Rust comprises three distinct phases.

    1. Phase 1 (Weeks 1 to 4): substantial frustration. The compiler rejects code consistently. Every attempt at straightforward activity, including passing data between functions, storing references in structs and writing concurrent code, triggers ownership violations that are difficult to reason about. Many developers abandon Rust in this phase.
    2. Phase 2 (Weeks 4 to 12): grudging respect. The borrow checker begins to make sense. The developer understands why the compiler requires what it requires and begins to see the bugs that the compiler is preventing. Code compiles more consistently.
    3. Phase 3 (Months 3 and beyond): appreciation. The developer writes safer code even in other languages. The recognition that compiling Rust code usually works correctly takes hold. The investment in working with the borrow checker pays off in the form of code that does not fail in production.

    Python, by contrast, is widely known for its gentle onboarding. Most developers write working Python within days of starting. The language’s design explicitly targets readability and minimal syntax. “There should be one obvious way to do it” is a core Python principle. For developers new to programming, Python is the natural starting point.

    # Python: Read a file and count word frequencies
    from collections import Counter
    
    with open("text.txt") as f:
        words = f.read().lower().split()
    
    word_counts = Counter(words)
    print(word_counts.most_common(10))
    
    // Rust: Same task — more explicit but equally safe
    use std::collections::HashMap;
    use std::fs;
    
    fn main() {
        let content = fs::read_to_string("text.txt")
            .expect("Failed to read file");
    
        let mut word_counts: HashMap<String, usize> = HashMap::new();
    
        for word in content.split_whitespace() {
            let word = word.to_lowercase();
            *word_counts.entry(word).or_insert(0) += 1;
        }
    
        let mut counts: Vec<(&String, &usize)> = word_counts.iter().collect();
        counts.sort_by(|a, b| b.1.cmp(a.1));
    
        for (word, count) in counts.iter().take(10) {
            println!("{}: {}", word, count);
        }
    }
    

    The output is identical. Python is more concise. Rust is more explicit regarding types and error handling, but at compile time the compiler guarantees that the Rust version will not panic unexpectedly in production (unless the developer requests such behaviour with expect).

    Real-World Use Cases: Where Each Language Predominates

    Where Python Predominates

    Data Science and Machine Learning. No alternative matches Python’s ecosystem. NumPy, Pandas, scikit-learn, PyTorch, TensorFlow, JAX and Hugging Face represent billions of dollars of engineering investment, and they are Python-first. A data scientist who switches to Rust for ML work does not obtain a better ecosystem; they find a substantially smaller one.

    Rapid Prototyping and Research. When the goal is to test an idea quickly, Python’s expressiveness is unmatched. A Python prototype that works in 200 lines might require 600 lines in Rust and additional days of development. For research and experimentation, this matters substantially.

    Scripting and Automation. Python’s standard library includes tools for file manipulation, network requests, regular expressions, parsing JSON, XML and YAML, and most common automation tasks. For DevOps scripts, data processing pipelines and administrative tools, Python’s combination of readability and library richness is difficult to surpass.

    Web Backends for Data-Heavy Applications. When the backend principally serves data from a database and integrates with data science workflows, Python’s FastAPI or Django provides everything needed at reasonable performance. The complete guide to building REST APIs with FastAPI demonstrates how quickly a developer can go from zero to a production-ready API in Python.

    Where Rust Predominates

    Systems Programming. Operating system components, device drivers, embedded systems and firmware, all of which run close to the hardware under strict memory constraints. Rust is rapidly replacing C for new systems code at companies that have experienced C’s memory safety issues.

    High-Performance Network Services. HTTP proxies, DNS resolvers, message queues and game servers, all of which require low latency and high throughput and cannot tolerate garbage collection pauses. The Cloudflare engineering blog has published multiple case studies on replacing CPU-intensive services with Rust implementations and obtaining 10x improvements in efficiency.

    WebAssembly. Rust is the premier language for WebAssembly (WASM), the bytecode format that enables high-performance code to run in web browsers. The Rust-to-WASM toolchain is mature, and Rust WASM modules are used in production by Figma, Shopify and others for compute-intensive browser-side code.

    CLI Tools. Rust’s fast startup time, compared with Python’s 100 to 500 ms import overhead, its static binaries, which require no runtime, and its strong argument parsing libraries make it well suited to command-line tools that must feel instantaneous. Packaging these tools with Docker containers simplifies distribution further, regardless of language. Many widely used developer tools, including ripgrep, fd, bat, exa and delta, are Rust reimplementations of Unix tools that are substantially faster than their predecessors.

    Cryptocurrency and Blockchain. Solana, the high-performance blockchain, is built primarily in Rust. Where smart contract bugs can result in millions of dollars lost instantly, Rust’s safety guarantees become economic necessities rather than engineering preferences.

    Python + Rust: A Combined Approach

    One of the most important developments in the Python ecosystem over the past three years is the maturation of PyO3, a Rust library that makes writing Python extension modules in Rust straightforward. This enables a powerful hybrid architecture: high-level logic, ML pipeline orchestration and user-facing APIs are written in Python, while performance-critical inner loops are implemented in Rust.

    This pattern is already in production at major organisations. Pydantic v2, used by millions of Python developers for data validation, rewrote its core validation engine in Rust via PyO3, achieving 5 to 50 times performance improvements while maintaining a pure Python API. Polars, a DataFrame library competing with Pandas, is built in Rust with a Python interface and consistently outperforms Pandas by 5 to 30 times across most benchmarks. The tokenizers library from Hugging Face, used to prepare text for LLM training, is implemented in Rust, enabling 20-fold speedups in text preprocessing.

    # Using Polars (Rust-backed) instead of Pandas
    import polars as pl
    
    # This reads and processes the CSV using Rust under the hood
    df = (
        pl.read_csv("large_dataset.csv")
        .filter(pl.col("revenue") > 1_000_000)
        .group_by("region")
        .agg(pl.col("revenue").sum().alias("total_revenue"))
        .sort("total_revenue", descending=True)
    )
    
    print(df.head(10))
    # Typically 5-20x faster than equivalent Pandas code
    
    Tip: A choice between Python and Rust is not necessary for most projects. The hybrid approach, Python for orchestration and Rust for performance-critical operations, is increasingly common and well supported. For Python developers encountering performance limits, learning sufficient Rust to write PyO3 extensions is often more valuable than switching languages entirely.

    Career Impact: What These Languages Mean for the Job Market

    Python remains the most in-demand programming language for job postings in 2026. Its dominance in data science, ML engineering and web development makes Python skills valuable in virtually every technology company. According to the 2025 Stack Overflow Developer Survey, Python is the most popular language for the fourth consecutive year among all developers, and the most popular by a substantial margin among data scientists and ML engineers.

    The Rust job market is smaller but growing rapidly and is remarkably well compensated. Rust developers are scarce, since the language’s difficulty creates a supply constraint, and they are disproportionately hired into high-value infrastructure roles, including distributed systems, compilers, operating systems and high-frequency trading infrastructure. Average Rust developer salaries consistently rank among the highest in software engineering compensation surveys.

    The career-optimisation observation is as follows: Python is a floor, Rust is a ceiling. Python provides broad access to the job market. Rust provides access to the highest-complexity, highest-compensation engineering roles that currently exist. For developers who wish to work on the software that runs internet infrastructure, Rust is an increasingly important skill. For developers who wish to work in data science, ML or general software engineering, Python remains the most versatile investment.

    The Decision Framework

    Having examined performance benchmarks, memory models, learning curves and ecosystem comparisons, the decision often reduces to something simpler than any technical metric: what is actually being built?

    If the project involves data pipelines, ML models, web APIs, automation scripts or any application in which correctness and developer velocity matter more than raw performance, Python is almost certainly the appropriate choice. Following clean code principles matters in either language, but Python’s readability makes it a natural fit for maintainable codebases. Its ecosystem, readability and breadth of available libraries make it the most productive choice across a wide range of problems.

    If the project involves infrastructure software, systems tools, high-performance services, embedded applications or any context in which memory safety, predictable performance and runtime efficiency are paramount, Rust merits serious consideration. Its compile-time safety guarantees and zero-overhead abstractions make it the most compelling new systems language in decades.

    For a developer deciding which language to learn first, Python is the recommended starting point. It produces productivity faster, provides access to the richest ecosystem of libraries in any language, and is immediately applicable to data science, web development, automation and most other domains. Adopting Git and GitHub best practices from the start keeps projects organised during learning. When a problem arises in which Python’s performance or safety characteristics become the bottleneck, the developer will then have the context to appreciate what Rust offers and the motivation to invest in its steeper learning curve.

    The elevator that crashed in 2006 prompted a language that now runs in the Linux kernel, Android’s Bluetooth stack and Cloudflare’s global network infrastructure. Guido van Rossum’s hobby project is now the foundation of the modern AI revolution. Both outcomes were unimaginable to their originators at the time. The tools developers build, and the tools they choose to use, shape the software that shapes the world. The choice deserves careful thought.

    Decision Tree: Python or Rust? Start: New Project Does your project involve ML, data science, scripting, or rapid prototyping? YES Use Python Best ecosystem fit NO Is runtime performance or memory safety critical? YES Use Rust Systems / infra / CLI NO Is developer velocity the top priority? YES Use Python Productivity wins NO Consider Python + Rust PyO3 hybrid approach This is a guide, not a rule—context always matters


    References