> ## Documentation Index
> Fetch the complete documentation index at: https://docs.circuit.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Multi-Agent Monorepo

> Run multiple agents from one repository and share code between them with native package-manager workspaces (uv for Python, Bun for TypeScript).

<Note>Building a single agent? Skip this - a standalone project (what `circuit new` creates) is all you need. This page is for running multiple agents from one repository and sharing code between them.</Note>

## Two repository structures

The CLI supports two shapes, and **detects which one you're in automatically** - there is no mode flag or `circuit.toml` setting to choose.

| Structure              | When                                                  | Shared code                   |
| ---------------------- | ----------------------------------------------------- | ----------------------------- |
| **Standalone agent**   | One agent, self-contained (the `circuit new` default) | None                          |
| **Workspace monorepo** | Multiple agents sharing code                          | Native workspace **packages** |

In a workspace, shared code lives in real packages that each **own their dependencies**, and an agent depends on them by name - the same pattern any uv/Bun monorepo uses. No import-path hacks, no per-agent dependency duplication. When you upload, the CLI installs the depended-on packages into the agent's deploy bundle; the running agent is shaped exactly like a standalone one.

## Layout

A single-language monorepo: a workspace root manifest beside `agents/` and `packages/`.

<CodeGroup>
  ```text Python theme={null}
  my-agents/
  ├── pyproject.toml          # [tool.uv.workspace] root (virtual - no [project])
  ├── uv.lock                 # one lockfile for the whole workspace
  ├── agents/
  │   └── trading-bot/
  │       ├── main.py
  │       ├── circuit.toml
  │       ├── DESCRIPTION.md
  │       └── pyproject.toml
  └── packages/
      └── hyperliquid/        # a shared package → import as lib.hyperliquid
          ├── pyproject.toml
          └── lib/
              └── hyperliquid/   # no lib/__init__.py - PEP 420 namespace
                  ├── __init__.py
                  └── positions.py
  ```

  ```text TypeScript theme={null}
  my-agents/
  ├── package.json            # { "workspaces": ["agents/*", "packages/*"] }
  ├── bun.lock                # one lockfile for the whole workspace
  ├── agents/
  │   └── trading-bot/
  │       ├── index.ts
  │       ├── circuit.toml
  │       ├── DESCRIPTION.md
  │       ├── package.json
  │       └── tsconfig.json
  └── packages/
      └── polymarket/         # a shared package
          ├── package.json
          └── src/index.ts
  ```
</CodeGroup>

## Python (uv workspace)

**1. Declare the workspace at the repo root.** A virtual root (no `[project]`) is enough:

```toml theme={null}
# pyproject.toml
[tool.uv.workspace]
members = ["agents/*", "packages/*"]
```

**2. Make the shared code a package** that owns its dependencies. Group shared packages under a namespace of your choosing (here, `lib`) so they read as `lib.<pkg>`:

```toml theme={null}
# packages/hyperliquid/pyproject.toml
[project]
name = "lib-hyperliquid"   # must be unique + not clash with a real PyPI package
version = "0.0.0"
requires-python = ">=3.14"
dependencies = ["numpy", "pandas"]   # the package owns these

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

# Preserve the lib/ prefix so the wheel installs to lib/hyperliquid (namespace).
[tool.hatch.build.targets.wheel]
only-include = ["lib/hyperliquid"]
```

<Note>
  `name` is the **distribution name** (the key the agent depends on and that
  `[tool.uv.sources]` resolves), not the import path. Give shared packages a
  prefix like `lib-`: the workspace resolves to a single version and a workspace
  package wins over the registry, so a bare `name = "hyperliquid"` would shadow the
  PyPI package of that name and no member could install the real one. The prefix
  keeps shared code in a private namespace that can't collide with a registry
  dependency. (The import path `lib.hyperliquid` comes from `only-include`, not
  from `name`.)
</Note>

**3. Depend on it from the agent** via a workspace source:

```toml theme={null}
# agents/trading-bot/pyproject.toml
[project]
name = "agent-trading-bot"   # unique per agent - members share one resolution
version = "0.0.0"
requires-python = ">=3.14"
dependencies = ["lib-hyperliquid"]

[tool.uv.sources]
lib-hyperliquid = { workspace = true }
```

**4. Import it by name** - no `sys.path` manipulation:

```python theme={null}
from lib.hyperliquid.positions import get_positions
```

Run `uv lock` once at the root and commit the `uv.lock`.

## TypeScript (Bun workspace)

**1. Declare the workspace at the repo root:**

```json theme={null}
// package.json
{ "private": true, "workspaces": ["agents/*", "packages/*"] }
```

**2. Make the shared code a package** that owns its dependencies:

```json theme={null}
// packages/polymarket/package.json
{
  "name": "@lib/polymarket",
  "main": "src/index.ts",
  "dependencies": { "viem": "2.48.4" }
}
```

**3. Depend on it from the agent:**

```json theme={null}
// agents/trading-bot/package.json
{
  "name": "@circuit/agent-trading-bot",
  "main": "index.ts",
  "dependencies": {
    "@lib/polymarket": "workspace:*",
    "viem": "2.48.4"
  }
}
```

**4. Import it by name** - no `tsconfig` path aliases:

```typescript theme={null}
import { getPositions } from "@lib/polymarket";
```

Run `bun install` once at the root and commit the `bun.lock`.

## Mixing Python and TypeScript in one repo

uv requires every member-glob match to be a Python package, so a shared `agents/*` glob can't hold both flavors. Give each language its own workspace root:

```text theme={null}
my-agents/
├── python/        # pyproject.toml [tool.uv.workspace] + agents/ + packages/
└── typescript/    # package.json workspaces + agents/ + packages/
```

Upload each agent from its own directory as usual - the CLI walks up to the correct workspace root.

## Forking a workspace agent

Forking (or editing) a published workspace agent copies its stored source
into the builder **exactly as uploaded**: the workspace root config and
lockfile, the agent in its own directory, and the shared packages it depends
on beside it. Nothing is rewritten - `bun` / `uv` link the packages in the
builder the same way they do in your monorepo, and the lockfile carries over,
so the fork runs the same dependency versions the original published with.
The fork is still a snapshot: it starts as a copy of your code, not a live
link to your monorepo.

## Next steps

* [Execution Model](../concepts/execution-model) - how sessions and the run loop work
* [`circuit.toml` reference](./circuit-toml-reference)
