AGENTS.md

September 12, 2026 · View on GitHub

Standards for anyone — human or coding agent — working in this repository: the workspace map, the Definition of Done, and the conventions that keep changes consistent.

What this is (and isn't)

This is the repo-root contributor/agent standards doc — how to find your way around the B4.run monorepo, what "done" means for a change, and the rules that keep the codebase consistent. It's the canonical entrypoint; see Cross-links for how it relates to CONTRIBUTING.md and CONTRIBUTORS.md.

This is not the runtime workspace/AGENTS.md capability. B4.run ships a built-in capability (packages/core/src/capabilities/built-in/agents-md.ts) that auto-injects the contents of an app's <appRoot>/workspace/AGENTS.md into that agent's system prompt as its persistent "# Memory" — re-read every turn, updated by the agent itself via writeFile. That's an end-user B4.run app feature, documented at b4.run/docs/memory. The name collision is real: this file (repo root, for contributors) and that file (inside a generated app's workspace/, for the agent at runtime) share a filename but nothing else. If you're looking for the runtime feature, this isn't it.

Workspace map

Every packages/* directory is a pnpm workspace member (verify: pnpm -r list --depth -1). One-line purpose is each package's own README.md first line.

Core framework

PackagePurpose
@b4run/sdkThe author-facing TypeScript SDK — agent(), defineMiddleware(), allow()/reject(), and the type primitives the CLI consumes.
@b4run/coreFilesystem-based route discovery, app config loading, state-field resolution, and typegen primitives that the B4.run CLI builds on.
@b4run/cliThe b4 CLI — local HMR dev runtime, route execution, validation, typegen, and the build step that produces LangSmith deployment artifacts.
@b4run/langgraphLangGraph runtime adapters and route module contracts (graphAdapter, workflowAdapter, defineEntry) used by the CLI.
@b4run/langchainLangChain backend adapters — materializes chain routes and provider-aware agent routes (tool conversion, streaming, retry).

Capabilities & integrations

PackagePurpose
@b4run/ag-uiAG-UI protocol translation for B4.run's local runtime — maps runtime stream chunks to AG-UI events and back, so CopilotKit and other AG-UI clients can drive B4.run agents.
@b4run/permissionsPermission and access-control primitives for B4.run agents — gating tool and resource access at runtime.
@b4run/workspaceFilesystem-backed workspace utilities for B4.run agents — reading, writing, and managing files in an agent's working directory.
@b4run/sandboxReference sandbox providers for B4.run workspace execution — a Docker-backed SandboxProvider that redirects the workspace filesystem and shell tools into a per-thread isolated environment.
@b4run/vite-pluginVite plugin for B4.run's typegen pipeline (extracts tool types and generates route ambient declarations).

Storage & memory

PackagePurpose
@b4run/memoryDeterministic long-term memory storage and recall for B4.run's typed memory.ts capability — the storage/ranking layer under @b4run/core.
@b4run/memory-pgvectorPostgres + pgvector backend for B4.run's typed long-term memory store, for deployments where SQLite is too local (multiple instances, shared DB, HNSW retrieval at scale).
@b4run/sqlite-storageSQLite-backed storage adapter for B4.run — durable persistence for agent state and runtime data.
@b4run/postgres-storagePostgres backend for B4.run's durable runtime state — checkpointer, Agent Protocol threads store, and permissions store over one pg pool, for deployments where the .b4/ files are too local (multiple instances, shared DB, ephemeral filesystem).

Testing & evals

PackagePurpose
@b4run/testingTesting utilities for B4.run apps — helpers for exercising routes, tools, and agent behavior in unit and scenario tests.
@b4run/evalsEvaluation harness for B4.run agents — running and scoring agent behavior against datasets and scenarios.

Scaffolding & tooling

PackagePurpose
create-b4-appScaffold a new B4.run app — generates a working application from the supported starter templates with B4.run's canonical layout wired for local development.
@b4run/devkitInternal scaffold templates and dev-time tooling shared between @b4run/cli and create-b4-app.
@b4run/config-typescriptShared TypeScript compiler configurations (base, library, node, nextjs) for B4.run workspace packages.
@b4run/config-biomeShared Biome lint/format configuration used by B4.run workspace packages.

Apps

PackagePurpose
@b4run/web (apps/web)The documentation website (b4.run) and its content/nav.

Examples (examples/*, pnpm workspace members; consume B4.run via workspace:* and are typechecked in CI)

PackagePurpose
@b4-example/chat-server / @b4-example/chat-web (examples/chat)Foundational agent-harness primitives (filesystem + bash) end-to-end, plus planning, skills, subagents, workspace, and HITL permissions, with a disposable smoke-test web client.
@b4-example/memory (examples/memory/server)Long-term memory with a backend-switchable store — zero-setup SQLite by default, Postgres + pgvector via DATABASE_URL, hybrid keyword + vector recall via OPENAI_API_KEY.
@b4-example/research-server / @b4-example/research-web (examples/research)The flagship deep-research assistant example — routes, tools, subagents, memory, planning, offloading, HITL permissions, and an optional Docker sandbox.

Note: examples/chat/package.json and examples/research/package.json are orchestration-only (private: true, one level above server/web) and are not themselves pnpm workspace members — the actual members are the server/web subdirectories, matched by the examples/*/* glob in pnpm-workspace.yaml.

Charts (Helm charts under charts/, not pnpm workspace members)

ChartPurpose
charts/b4-appRuns a built B4.run app image on Kubernetes as a Deployment + Service, with optional Ingress, HorizontalPodAutoscaler, and PodDisruptionBudget, with an application-owned ServiceAccount in the chart release namespace. Sandbox access is bound cross-namespace to the b4-sandbox-infra orchestrator Role.
charts/b4-sandbox-infraCluster-side infrastructure for the B4.run kubernetesSandbox provider — namespace, least-privilege RBAC, default-deny egress, quotas/limits, Pod Security Standards, and a PVC reaper.

test/ and scripts/ are repo-level (verification lanes and workspace scripts respectively) — not workspace packages.

Definition of Done

The required validate job in .github/workflows/ci.yml aggregates four independent lanes for code and release-bearing changes and succeeds only when all four succeed. Failure, cancellation, or an unexpected skipped lane blocks it.

A pull request changing only regular, non-executable Markdown files under docs/superpowers/runbooks/ uses the narrow prose path. The existing scope job checks the exact merge-base diff, both sides of file modes, and whitespace before emitting that result. validate still runs and requires successful classification and all four heavy lanes to be deliberately skipped. Mixed changes, other paths, missing or malformed results, and failed classification cannot pass this route. All pushes to main retain full validation; generated-metadata scope remains a separate exception for its existing infrastructure jobs.

The source-validate lane runs these gates in order after installation:

  1. pnpm test:release-integrity — early content pins and recovery-policy checks
  2. pnpm lint
  3. pnpm check:build-cache
  4. pnpm build
  5. pnpm typecheck
  6. pnpm test
  7. pnpm check:release-inventory
  8. node scripts/check-docs.mjs

The release-controller lane installs dependencies, runs the early integrity checks, and runs the complete pnpm test:release-controller suite from an unbuilt checkout. The pack-smoke lane runs pnpm pack:check and pnpm verify:typescript-tooling-pack. The harness-verify lane runs pnpm verify:harness:self-test and the framework, runtime, and smoke harnesses. These gates remain part of repository validation.

On pull requests, a separate changesets job also runs node scripts/check-changesets.mjs to require a changeset for user-facing package changes.

Run pnpm ci:validate locally to run the validation commands sequentially. The script in the root package.json runs release-integrity → lint → build-cache → build → typecheck → source-test → release-inventory → release-controller-test → docs-check → pack-check → TypeScript-tooling-pack → harness sequence, plus the local-only test:sync-chart-appversion release-script unit test, which is not a separate CI step. The former publish, upload, and backfill unit-test commands were removed with their legacy release owners; their replacement coverage is part of test:release-controller.

Gated lanes — these run as separate CI jobs behind env flags or dedicated infrastructure, not part of validate, and aren't required for most PRs: sandbox-docker (B4_TEST_DOCKER=1), pgvector-docker (B4_TEST_PGVECTOR=1), postgres-storage-docker (B4_TEST_PGSTORAGE=1, Testcontainers postgres:16), sandbox-k8s (B4_TEST_K8S=1, kind + Calico), sandbox-k8s-e2e / sandbox-docker-e2e (B4_TEST_SMOKE_E2E=1, full-arc deployed-app smoke), chart-validate (Helm lint + kubeconform), and chart-apply-smoke (kind install smoke).

Release-bearing changes must also leave the separate copilotkit-examples-e2e and real vercel-native production-boundary jobs green. The CopilotKit examples exercise the v2 integration surface, and the Vercel job creates, verifies, and removes real preview resources through the pinned Vercel CLI; neither lane is a substitute for the other or optional release cleanup.

Conventions

  • Changesets are a fixed group, patch on 0.x. All publishable packages release together (.changeset/config.json's fixed group). On a 0.x train a minor bump takes every package to 1.0.0 — use patch unless you intend a real 1.0 release.
  • exactOptionalPropertyTypes: true. Never assign { x: undefined } to an optional field; use a conditional spread (...(x !== undefined ? { x } : {})) instead, or the type checker will reject it.
  • Never run bare biome check --write. It mass-reformats the whole workspace. Use pnpm lint (or pnpm lint:fix to auto-fix), or scope Biome to the files you changed.
  • Import specifiers: src/ uses .js, test/ uses .ts. This is NodeNext ESM — source files import sibling src/*.ts modules with a .js extension; test files import with .ts. Follow the existing pattern in the package you're editing.
  • Examples/docs/scaffolds use gpt-5-family models only (canonical default gpt-5-mini; no gpt-4o, though it stays in the provider registry, validation tests, and recorded fixtures). This is a project convention, not currently enforced by scripts/check-docs.mjs — check it by eye when touching examples.
  • Branch per PR; pin before dispatching parallel/subagent work. In a multi-worktree setup, a subagent's commits can land on a detached HEAD tracking the wrong branch if the feature branch isn't checked out first.
  • Limit simultaneous full CI submissions. Prepare independent changes locally in parallel, but normally keep at most two maintainer-managed PRs with full CI active at once, accounting for validation already running on main. Wait for active runs before pushing a follow-up head. Do not cancel release runs or add a repository-wide serialization gate; this is submission guidance. During performance work, submit one performance PR at a time so its impact is clear.
  • Build before running anything against dist/. Packages compile src/*.ts to a gitignored dist/, and consumers import the built output — a stale or skewed dist/ (from a branch switch or a per-package filtered build) produces false negatives in ad-hoc scripts. Run pnpm build first; see CONTRIBUTING.md's "Build before running anything against dist/".
  • Banned doc phrases. scripts/check-docs.mjs greps README.md, CONTRIBUTING.md, CONTRIBUTORS.md, SECURITY.md, CODE_OF_CONDUCT.md, apps/web/app, apps/web/content, docs/ (excluding docs/superpowers/), and packages/ for stale or overstated wording — e.g. the retired b4.run domain, provider-prefixed model ids (openai:gpt...), the old agent.bindTools / .b4/generated / auto-bound/auto-registered phrasing, and claims like "byte-identical" or "speaks the LangSmith protocol natively" that overstate local/prod parity. This file (AGENTS.md) isn't in that scanned set, but keep it honest anyway — see the forbiddenContent list in scripts/check-docs.mjs for the exact patterns.
  • Always run commands from the repo root. Turbo and workspace-package resolution assume it.
  • Every final-workflow-reachable release script is content-pinned. The audited SHA256 and exact command line for each repository script reachable from the final release-owner workflows are recorded in scripts/release/test/fixtures/release-script-hashes.json. Editing a reachable script, adding an unpinned entrypoint, or retaining a stale pin fails pnpm test:release-controller until the reviewed fixture is regenerated in the same commit. The pin file also has a reviewed digest snapshot in scripts/release/test/workflow-contracts.test.mjs; intentional pin changes must update that snapshot too. Run that focused test file alongside pnpm test:release-integrity before the full controller suite to catch mismatched snapshots early. Reachability is re-derived from workflow run: steps, package-script expansion, and action with: inputs, and then closed transitively over each entrypoint's repository-local module loads — static import/export ... from, dynamic import() with a literal specifier, and the new URL("./sibling.mjs", import.meta.url) form the release CLI hands to its injected loader. A load whose specifier cannot be resolved statically fails the check rather than being skipped; the reviewed exceptions live in REVIEWED_DYNAMIC_IMPORT_SEAMS. Files a pinned module reads off disk instead of importing are declared in RELEASE_DATA_FILES and anchored to a reader. This is deliberately limited to release ownership; ordinary CI-only scripts are not pinned. See CONTRIBUTORS.md's "Release Integrity Coverage" for the boundary.

Where things live

  • Docs site content: apps/web/content/docs/*.mdx (nav registered in apps/web/app/components/docs/nav.ts).
  • Specs, plans, audits, runbooks: docs/superpowers/.
  • CI: .github/workflows/ci.yml.
  • Changeset config (fixed group, patch-on-0.x): .changeset/config.json.
  • CONTRIBUTING.md — the public PR path: setup, issues, PRs, CLA/DCO, code of conduct.
  • CONTRIBUTORS.md — internal monorepo guide: local setup, the --mode internal scaffold path, and verification lanes. Its per-package responsibilities point back at the workspace map above.
  • README.md — project overview and quickstart.