Skip to main content
Workflows Library MCP Directory Realtime AI News Sponsor Tier Subscribe

Build a Company-Wide Multi-Agent Harness with LangGraph

Y Combinator open-sourced QM (MIT license, GitHub org yc-software) as a multiplayer multi-agent harness built for a whole company rather than a single user - it runs YC's own accounting, legal, events, and engineering work, including developing QM itself. Cloud-first with native Slack and web interfaces and model-agnostic across Pi, OpenCode, Codex, and Claude Code. This dispatch builds company-harness, a LangGraph workflow with a task intake router, a role router dispatching to role-appropriate agents on swappable model backends, an approval board for cross-role decisions, unified observability and audit, and a self-improvement loop that files tasks back into the queue.

Deepak Bagada

Deepak Bagada

CEO, SaaSNext

Aug 19, 2026 Published
|
Aug 19, 2026 Updated
|
11 Minutes Reading Time
Core Takeaways for Founders & Builders
  • Model roles as durable entities and agents as ephemeral workers - role manifests hold skills, permissions, escalation rules, and auto-ok thresholds.
  • Model-agnosticism is a config decision: a role's permitted backend set plus a normalized adapter make backend failover a config line, not a refactor.
  • The approval board auto-oks only above a measured eval score; cross-role and high-risk actions always hit a human, with a timeout that silently rejects.
  • Eval gates record a per-decision confidence score, which doubles as the compliance and audit story.
  • Self-improvement is bounded: failing evals re-file a tighter task into intake, capped at two rework rounds before a human steps in.

By Deepak Bagada, CEO at SaaSNext & Principal AI Architect.

Build a Company-Wide Multi-Agent Harness with LangGraph

In 2026, Y Combinator open-sourced QM (MIT license, GitHub org yc-software) and the one-word summary is multiplayer. QM is not an agent that answers questions for a single developer; it is a "multiplayer" multi-agent harness designed for a whole company. YC itself runs accounting, legal, events, and engineering work on it — including developing QM with QM. It is cloud-first, ships native Slack and web interfaces, and is deliberately model-agnostic: the same orchestration loop runs on Pi, OpenCode, Codex, or Claude Code, whichever model happens to be best at a given task on a given day. That is the "harness" framing: the orchestration is the product, the model is a swappable worker.

The mental shift matters. A single-user agent needs context and tools. A company harness needs roles, routing, permissions, approvals, and governance — because the moment agents can touch accounting, legal, and engineering simultaneously, "the model" is no longer the risk surface. The routing and approval layers are. This dispatch builds company-harness, a LangGraph workflow that generalizes QM's architecture: a task intake router (Slack, web, email), a role router that dispatches to the right agent on the right model backend through a model-agnostic adapter, an approval board for cross-role decisions, a unified observability and audit layer, and a self-improvement loop where agents can file tasks back into the intake queue.

The architecture: roles, not agents

The first design decision is to model roles as the durable entities and agents as ephemeral workers. Engineering, Finance, Legal, and Ops each have a role manifest: what skills they hold, what they may touch, what they must not touch, and what they must escalate. A worker is just "role X instantiated on backend Y". This is exactly what makes QM model-agnostic workable — you swap the backend without re-architecting the role, and you can A/B two models on the same task type safely because the permissions and eval gates do not change.

flowchart TD
    A[Slack / Web / Email intake] --> B[task_intake_router]
    B --> C{role router}
    C -->|engineering| D[eng agent]
    C -->|finance| E[fin agent]
    C -->|legal| F[legal agent]
    C -->|ops| G[ops agent]
    D --> H{approval board}
    E --> H
    F --> H
    G --> H
    H -->|cross-role or risky| I[human approve]
    H -->|auto-ok| J[eval gate]
    I --> J
    J -->|pass| K[executor]
    J -->|fail| L[rework queue]
    L --> C
    K --> M[observability + audit]
    M --> N{self-improve?}
    N -->|yes| A
    N -->|no| O[Done]

Notice the self-improvement loop in the bottom corner: the harness does not end at completion. If the observability layer detects a recurring failure signature, the audit node files a new task back into the intake queue — "refactor the payment validation helper" is as legitimate a task as "fix the staging deploy", and it keeps the system improving itself the way YC's own QM develops QM.

Configuration: .env

# Backends (model-agnostic: pick per role, not globally)
BACKEND_PI_API=...        # Pi
BACKEND_OPENCODE_API=...  # OpenCode
BACKEND_CODEX_API=...     # Codex
BACKEND_CLAUDE_API=...    # Claude Code
DEFAULT_BACKEND=claude-code

# Intake channels
SLACK_BOT_TOKEN=xoxb-...
SLACK_SIGNING_SECRET=...
WEB_HOOK_URL=https://harness.example/tasks
EMAIL_IMAP_HOST=imap.example.com

# Role routing
ROLE_ENGINEERING_MODELS=open-code,claude-code
ROLE_FINANCE_MODELS=pi,claude-code
ROLE_LEGAL_MODELS=pi
ROLE_OPS_MODELS=claude-code

# Governance
AUTO_OK_THRESHOLD=0.9          # eval score above which no human needed
CROSS_ROLE_ALWAYS_APPROVE=true
APPROVAL_BOARD_CHANNEL=#approvals

# Observability
OTEL_EXPORTER=otlp://otel-collector:4317
AUDIT_SINK=postgresql://audit:audit@localhost:5432/audit
LOG_LEVEL=INFO

The role→model mapping is the crux of model-agnosticism done right. You do not pick one model for the company; you pick a default and a permitted set per role, and the role router picks from the set. Legal gets Pi (best at long-context contractual reasoning), engineering gets OpenCode and Claude Code, and ops defaults to whatever is cheapest that still passes the eval gate.

Schemas: schemas.py

from __future__ import annotations
from datetime import datetime, timezone
from enum import Enum
from typing import Any

from pydantic import BaseModel, Field

class Role(str, Enum):
    ENGINEERING = "engineering"
    FINANCE = "finance"
    LEGAL = "legal"
    OPS = "ops"

class Backend(str, Enum):
    PI = "pi"
    OPENCODE = "open-code"
    CODEX = "codex"
    CLAUDE_CODE = "claude-code"

class TaskSource(str, Enum):
    SLACK = "slack"
    WEB = "web"
    EMAIL = "email"

class TaskPriority(str, Enum):
    P0 = "p0"
    P1 = "p1"
    P2 = "p2"

class Task(BaseModel):
    task_id: str
    source: TaskSource
    channel: str                    # slack channel / web form id / mailbox
    author: str
    title: str
    body: str
    priority: TaskPriority = TaskPriority.P2
    labels: list[str] = Field(default_factory=list)
    routed_role: Role | None = None
    assigned_backend: Backend | None = None
    created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))

class RoleManifest(BaseModel):
    role: Role
    skills: list[str] = Field(default_factory=list)
    allowed_backends: list[Backend]
    permissions: dict[str, list[str]] = Field(default_factory=dict)  # resource -> verbs
    must_escalate: list[str] = Field(default_factory=list)
    auto_ok_threshold: float = 0.9

class ApprovalRequest(BaseModel):
    approval_id: str
    task_id: str
    reason: str                     # cross_role | high_risk | low_confidence | irreversible
    role: Role
    risk_level: str                 # low | medium | high
    requested_by: str               # agent id
    status: str = "pending"         # pending | approved | rejected
    decided_by: str | None = None
    decided_at: datetime | None = None

class EvalResult(BaseModel):
    task_id: str
    role: Role
    backend: Backend
    score: float = 0.0              # 0..1 eval-gate score
    criteria: dict[str, float] = Field(default_factory=dict)
    passed: bool = False

class AgentRun(BaseModel):
    run_id: str
    task_id: str
    agent_id: str
    role: Role
    backend: Backend
    model_name: str
    tokens_in: int = 0
    tokens_out: int = 0
    cost_inr: float = 0.0
    started_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
    finished_at: datetime | None = None

class AuditEntry(BaseModel):
    entry_id: str
    run_id: str
    task_id: str
    actor: str
    action: str                     # intaked | routed | approved | eval | executed | self_filed
    detail: dict[str, Any] = Field(default_factory=dict)
    timestamp: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))

RoleManifest is where governance lives: permissions maps a resource to the verbs a role may perform, must_escalate lists actions that can never be auto-ok'd, and auto_ok_threshold sets how much confidence an eval must show before a human approval is skipped. A finance agent with permissions={"payments": ["read"]} cannot pay anything — it can only review.

External I/O with retry: tools.py

import asyncio
import random
from datetime import datetime, timezone

import httpx

class BackendDown(RuntimeError):
    pass

class NoBackendAvailable(BackendDown):
    pass

async def with_retry(coro_factory, *, attempts=4, base=0.3, max_backoff=5.0):
    for attempt in range(1, attempts + 1):
        try:
            return await coro_factory()
        except (httpx.TimeoutException, httpx.HTTPStatusError) as exc:
            if attempt == attempts:
                raise BackendDown(str(exc)) from exc
            delay = min(max_backoff, base * (2 ** (attempt - 1))) * (1 + random.uniform(0, 0.3))
            await asyncio.sleep(delay)

BACKENDS = {
    Backend.PI: {"url": "https://api.pi.example", "api_key_env": "BACKEND_PI_API"},
    Backend.OPENCODE: {"url": "https://api.opencode.example", "api_key_env": "BACKEND_OPENCODE_API"},
    Backend.CODEX: {"url": "https://api.codex.example", "api_key_env": "BACKEND_CODEX_API"},
    Backend.CLAUDE_CODE: {"url": "https://api.claude.example", "api_key_env": "BACKEND_CLAUDE_API"},
}

def backend_client(backend: Backend) -> httpx.AsyncClient:
    cfg = BACKENDS[backend]
    return httpx.AsyncClient(base_url=cfg["url"],
                             headers={"Authorization": f"Bearer {os.getenv(cfg['api_key_env'])}"})

async def call_model(backend: Backend, messages: list[dict], role: Role) -> dict:
    """Model-agnostic adapter: same request shape, backend-specific auth/endpoint."""
    async def call():
        async with backend_client(backend) as client:
            r = await client.post("/v1/chat/completions",
                                  json={"model": os.getenv(f"MODEL_{backend.value.upper()}"),
                                        "messages": messages,
                                        "role": role.value,
                                        "temperature": 0.2})
            r.raise_for_status()
            return {"text": r.json()["choices"][0]["message"]["content"],
                    "usage": r.json()["usage"]}
    return await with_retry(call)

async def send_slack(channel: str, text: str) -> None:
    async def call():
        async with httpx.AsyncClient(
                headers={"Authorization": f"Bearer {os.getenv('SLACK_BOT_TOKEN')}"}) as client:
            r = await client.post("https://slack.com/api/chat.postMessage",
                                  json={"channel": channel, "text": text})
            r.raise_for_status()
    await with_retry(call, attempts=3)

async def approve_via_board(request: ApprovalRequest) -> ApprovalRequest:
    """Post to #approvals, poll for a human verdict, timeout after 8h."""
    await send_slack(os.getenv("APPROVAL_BOARD_CHANNEL"),
                     f"Approval {request.approval_id}: {request.reason} "
                     f"for {request.role.value} task {request.task_id}")
    deadline = datetime.now(timezone.utc).timestamp() + 8 * 3600
    while datetime.now(timezone.utc).timestamp() < deadline:
        status = await check_approval_status(request.approval_id)
        if status in ("approved", "rejected"):
            request.status, request.decided_at = status, datetime.now(timezone.utc)
            return request
        await asyncio.sleep(30)
    request.status = "rejected"   # timeout = silent reject
    return request

async def run_eval_gate(task: Task, role: Role, backend: Backend,
                        agent_output: str) -> EvalResult:
    """Deterministic gates first (schema/perms), model-grade last."""
    criteria = {}
    criteria["schema_valid"] = 1.0 if agent_output else 0.0
    criteria["perm_respect"] = await check_permission_compliance(task, role, agent_output)
    criteria["factual_grounding"] = await grade_grounding(task, role, backend, agent_output)
    score = sum(criteria.values()) / len(criteria)
    return EvalResult(task_id=task.task_id, role=role, backend=backend,
                      score=score, criteria=criteria,
                      passed=score >= role_manifest(role).auto_ok_threshold)

async def append_audit(entry: AuditEntry) -> None:
    async def call():
        async with httpx.AsyncClient() as client:
            r = await client.post(os.getenv("AUDIT_SINK"), json=entry.model_dump())
            r.raise_for_status()
    await with_retry(call, attempts=3)

The adapter (call_model) is the whole game of model-agnosticism in one function: request shape is normalized, auth is backend-specific, and the routing graph never knows or cares which vendor answered. If you want to follow the broader ecosystem of such adapters, our MCP directory tracks the tooling layer underneath them.

The graph: graph.py

from typing import TypedDict

from langgraph.graph import END, StateGraph

from schemas import ApprovalRequest, AuditEntry, EvalResult, Task
from tools import (append_audit, approve_via_board, call_model, run_eval_gate,
                   send_slack)

class HarnessState(TypedDict):
    task: Task
    route: str
    role_manifest: dict
    agent_output: str | None
    approval: ApprovalRequest | None
    eval: EvalResult | None
    audit: list[AuditEntry]

async def intake_router(state: HarnessState):
    """Normalize Slack/web/email into a Task; classify source + priority."""
    task = state["task"]
    task.priority = classify_priority(task.title, task.body)
    await append_audit(AuditEntry(entry_id=uuid4().hex, run_id=state["run_id"],
                                  task_id=task.task_id, actor="intake",
                                  action="intaked", detail={"priority": task.priority.value}))
    return {"task": task}

def role_router(state: HarnessState) -> str:
    """Deterministic classifier → Role, then pick a backend from the role's set."""
    role = classify_role(state["task"])          # keyword + embedding classifier
    backends = ROLE_MODELS[role.value]
    state["task"].routed_role = role
    state["task"].assigned_backend = select_backend(backends, state["task"])
    state["route"] = role.value
    return role.value

async def run_agent(state: HarnessState):
    role, backend = state["task"].routed_role, state["task"].assigned_backend
    prompt = build_role_prompt(state["task"], role_manifest(role))
    resp = await call_model(backend, [{"role": "user", "content": prompt}], role)
    state["agent_output"] = resp["text"]
    return {"agent_output": resp["text"]}

def approval_router(state: HarnessState):
    """Auto-ok vs board: cross-role, high-risk, or low-confidence goes to humans."""
    req = build_approval_request(state["task"], state["role_manifest"], state["eval"])
    if req is None:
        return "eval"      # no approval needed
    return "approval"

async def approval_board(state: HarnessState):
    state["approval"] = await approve_via_board(state["approval"])
    return {"approval": state["approval"]}

def route_after_approval(state: HarnessState) -> str:
    if state["approval"].status == "approved":
        return "eval"
    return "done_rejected"

async def eval_gate(state: HarnessState):
    state["eval"] = await run_eval_gate(state["task"], state["task"].routed_role,
                                        state["task"].assigned_backend, state["agent_output"])
    return {"eval": state["eval"]}

def route_after_eval(state: HarnessState) -> str:
    if state["eval"].passed:
        return "execute"
    return "rework"

async def executor(state: HarnessState):
    """Apply approved+verified output: merge PR, post invoice, file form, deploy."""
    result = await apply_output(state["task"], state["agent_output"])
    await append_audit(AuditEntry(entry_id=uuid4().hex, run_id=state["run_id"],
                                  task_id=state["task"].task_id, actor="executor",
                                  action="executed", detail={"result": result}))
    return {}

def rework_queue(state: HarnessState):
    """Failures file a tighter-scoped task back to intake (self-improvement)."""
    new_task = scope_down_task(state["task"], state["eval"])
    await file_to_intake(new_task)          # re-enters intake_router
    await append_audit(AuditEntry(entry_id=uuid4().hex, run_id=state["run_id"],
                                  task_id=state["task"].task_id, actor="eval",
                                  action="self_filed",
                                  detail={"score": state["eval"].score}))
    return {}

async def observability(state: HarnessState):
    """Unified trace + audit close-out; may file improvement tasks."""
    await push_trace(state)
    await append_audit(AuditEntry(entry_id=uuid4().hex, run_id=state["run_id"],
                                  task_id=state["task"].task_id, actor="otel",
                                  action="observed", detail={"eval": state["eval"].model_dump()}))
    return {}

builder = StateGraph(HarnessState)
builder.add_node("intake", intake_router)
builder.add_node("eng", run_agent)
builder.add_node("fin", run_agent)
builder.add_node("legal", run_agent)
builder.add_node("ops", run_agent)
builder.add_node("approval", approval_board)
builder.add_node("eval", eval_gate)
builder.add_node("execute", executor)
builder.add_node("rework", rework_queue)
builder.add_node("observe", observability)

builder.set_entry_point("intake")
builder.add_conditional_edges("intake", role_router,
                              {"engineering": "eng", "finance": "fin",
                               "legal": "legal", "ops": "ops"})
for r in ("eng", "fin", "legal", "ops"):
    builder.add_edge(r, "approval_router")   # 2-node micro-router
builder.add_edge("approval", "eval")
builder.add_conditional_edges("eval", route_after_eval,
                              {"execute": "execute", "rework": "rework"})
builder.add_edge("execute", "observe")
builder.add_edge("observe", END)
builder.add_edge("rework", END)

graph = builder.compile()

One deliberate simplification to call out: run_agent is registered under four names (eng, fin, legal, ops) but is the same function — role differences live in the prompt built from role_manifest, not in the node. That keeps the permission matrix in one place, which is what makes a company-wide harness auditable instead of a tangle of per-department glue.

Entrypoint: main.py

import asyncio
import os

from dotenv import load_dotenv
from graph import graph
from schemas import Task

load_dotenv()

async def run_tasks(tasks: list[Task]) -> None:
    for t in tasks:
        initial = {"task": t, "route": None, "role_manifest": ROLE_MANIFESTS,
                   "agent_output": None, "approval": None, "eval": None, "audit": []}
        print(f"--- {t.task_id}: {t.title} ({t.source.value}) ---")
        final = await graph.ainvoke(initial)
        tsk = final["task"]
        print(f"role={tsk.routed_role.value} backend={tsk.assigned_backend.value} "
              f"eval={final['eval'].score:.2f} status={final['eval'].passed}")

async def main():
    await run_tasks([
        Task(task_id="T-5001", source="slack", channel="#eng", author="priya",
             title="staging deploy failed on payment-mock", body="see trace ...",
             labels=["deploy", "payments"]),
        Task(task_id="T-5002", source="web", channel="finance-form", author="rahul",
             title="reconcile vendor invoices Q2", body="uploaded 47 PDFs ..."),
        Task(task_id="T-5003", source="email", channel="legal@inbox", author="legal-team",
             title="draft NDA rider for EV partnership", body="redline attached ..."),
    ])

if __name__ == "__main__":
    asyncio.run(main())

Three tasks, three roles, three backends — one harness. The intake router saw a Slack message, a web form, and an email and turned all three into the same Task shape; the role router sent them to engineering, finance, and legal; and each ran on a backend chosen from that role's permitted set. That is the QM thesis: the orchestration loop is the product, and the models underneath are interchangeable workers.

Retry Rules & Error Handling

Failure Backoff Fallback Escalation
Model backend timeout/5xx 0.3s→5.0s Switch backend within role's set All backends down → Slack + on-call
Slack API failure 0.3s→1.2s, 3 attempts Queue message in outbox Email fallback to task author
Approval board timeout (8h) Auto-reject (silent reject) Notify author to re-file
Eval gate fails No retry — deliberate Rework task with tighter scope Human review if score < 0.5
Executor apply fails 0.3s→5.0s Idempotent re-apply Compensation handler per task type
Audit sink down 0.3s→1.2s Local buffer Freeze executor; do not claim done

The model-backend row is the most company-specific: when OpenCode is slow, the fallback is not "wait longer" — it is Codex. Because the adapter normalizes everything, backend failover is a config change, not a refactor. That is the practical payoff of model-agnosticism.

Cost & Decision Matrix

Decision point Cost driver Cheap path Expensive path Rule
Role routing Classifier tokens Keyword + embedding classifier (~₹0.02/task) Long-context LLM re-read (₹1.50/task) Classifier first, LLM on ambiguity
Backend choice Model per-token price Ops/Legal default to cheapest passing model Premium model always Backend ≤ cheapest that passes eval
Approvals Human time Auto-ok at eval ≥ 0.9 Board for every task Threshold per role manifest
Eval gate 1 grading call/task Deterministic gates only (schema/perms) +LLM grounding grade Hybrid: deterministic first
Self-improvement Rework loops Cap rework depth at 2 Unlimited re-filing Rework depth ≤ 2, then human

Run the economics once and the pattern is obvious: routing a task through the classifier costs about the same as a single model token, while a wrong role routing costs a full wasted run plus a board review. The harness should spend aggressively on routing quality and stingily on everything downstream — which is exactly the opposite of most teams' instinct to spend on the biggest model and skip the routing layer.

What a company harness means for 2026 teams

YC open-sourcing QM under MIT is a strong signal that "multiplayer" agent infrastructure is becoming a commodity you run yourself rather than buy as a closed platform. The dividing line between the products that will survive and the ones that won't is no longer model quality — every vendor has a good model — it is governance: roles, routing, permissions, approvals, and audit. In Indian enterprise reality that means the harness is also your compliance story: an agent that touches invoices and NDAs must be explainable, permission-scoped, and fully logged, and the eval gates give your auditors a recorded confidence score for every automated decision. For more production patterns like this, browse the full library in AI Workflows, track the agent-tooling wave in our MCP directory, and don't miss the weekly roundups in Latest AI News.

Ship checklist

  • Roles before agents. Define what Finance may not do before you build what it can do.
  • Model-agnostic adapter from day one. The swap cost between backends must be a config line.
  • Approval board for cross-role and high-risk. Auto-ok only above a measured eval threshold.
  • Eval gates on everything. A recorded score is your audit story and your rework signal.
  • Self-improvement loop with a rework cap. Agents fix their own tooling — but max two re-files, then a human.

QM shows the destination: a company where accounting, legal, events, and engineering run through one multiplayer harness, each department on the model that suits it, every decision gated and logged. The harness is not a wrapper around an LLM — it is the operating system of the company's work. Build the roles, the routing, and the audit first, and the models become the most replaceable part of the whole system.

Executive Briefing

Enjoyed this breakdown? Get our morning dispatch in your inbox.

Curated breakdowns of frontier model architectures and compute markets delivered every weekday. Zero fluff.

Frequently Asked Questions
QM is Y Combinator's 'multiplayer' multi-agent harness, released under the MIT license in the yc-software GitHub org. Unlike single-user agent tools, it is designed for a whole company and actually runs YC's accounting, legal, events, and engineering work - including developing QM itself. It is cloud-first, ships native Slack and web interfaces, and is model-agnostic across Pi, OpenCode, Codex, and Claude Code.
A deterministic classifier (keywords plus an embedding classifier) assigns the task to engineering, finance, legal, or ops. Each role manifest carries a permitted backend set - for example legal gets Pi, engineering gets OpenCode and Claude Code - and the router picks the cheapest backend in that set that passes the role's eval gate.
It means the orchestration loop is backend-independent. One normalized adapter (call_model in tools.py) handles auth and endpoint differences, so swapping Pi for Codex is a configuration change in the role manifest, not a code change. It also lets you A/B two models on the same task type safely because permissions and eval gates are unchanged.
Cross-role tasks, high-risk actions, irreversible actions, and outputs below the auto-ok eval threshold always go to the board. The board posts to #approvals and polls for a verdict; if no human decides within the timeout (8 hours in this build), the request is silently rejected.
When an eval gate fails, the rework queue files a tighter-scoped version of the task back into intake rather than simply failing. The observability layer can also file improvement tasks on recurring failure signatures. Rework depth is capped at two rounds, after which the task is escalated to a human.
Deepak Bagada
Author Profile

Deepak Bagada

CEO, SaaSNext

Deepak Bagada is the CEO of SaaSNext and founder of Daily AI World. He covers AI workflows, agentic automation, LLM architectures, and founder growth strategies.

Related Intelligence Analysis

Research Breakdown AI Workflows

The Step-by-Step Guide to Automating Meeting Tasks with Whisper

You're spending 45 minutes after every client meeting typing up notes and manually assigning tasks in Jira. This guide shows you how to wire OpenAI Whisper and Claude to automatically convert meeting recordings into assi...

Deepak Bagada Deepak Bagada
9m read
Research Breakdown AI Workflows

Lovable AI UI-to-Code Pipeline: 2026 Tutorial

Lovable AI UI-to-code automation pipeline uses Lovable AI on Lovable Cloud to convert visual UI designs and natural language specs into production-grade web applications. UI/UX designers and frontend developers bridging...

Deepak Bagada Deepak Bagada
8m read
Breaking AI Workflows

Claude Code's New Browser: 5 Workflows That Save Hours Daily

Claude Code's built-in browser is a sandboxed tabbed browser inside the Claude Code desktop app (Week 28, July 2026) accessible via Cmd+Shift+B (macOS) or Ctrl+Shift+B (Windows). It lets Claude open websites, read docume...

Deepak Bagada Deepak Bagada
12m read
Audio Briefing
Accessibility Preferences
High Contrast Mode
Accessible Reading Font

Keyboard Shortcuts

Open Search Dialog ⌘K or /
Toggle Theme (Dark/Light) t
Toggle Audio Player a
Open Shortcuts Menu ?
Close Active Dialog Esc