Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ tmp
# Dev script logs
.dev-logs/

# Local (no-Docker) dev datastore data
agentex/.dev-local/

### PYTHON

# Byte-compiled / optimized / DLL files
Expand Down
21 changes: 21 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,27 @@ Other commands:
./dev.sh restart # Restart all services
```

Docker-free mode (host processes + embedded datastores, no Docker):
```bash
./dev.sh no-docker # whole stack without Docker (or: make dev-no-docker)
./dev.sh no-docker --lean # Postgres + Redis + API + MongoDB only
./dev.sh no-docker --mongo-uri <uri> # use an external MongoDB instead of a local mongod
```

> **MongoDB is required for the full no-docker stack** and is always started — the Temporal
> worker builds Mongo-backed repositories at startup, so a missing/unreachable Mongo
> makes the runner fail fast (with an install message) rather than crash the worker.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ty for adding here

> `./dev.sh no-docker` auto-installs `mongod`; `make dev-no-docker` / direct `python -m
> scripts.dev_nodocker` do not, so install `mongod` yourself or pass `--mongo-uri <uri>` to
> point at an external MongoDB. In no-docker mode the Temporal UI is on :8233 (Docker mode
> uses :8080).
>
> Agents register their ACP URL as `host.docker.internal` (for a Docker backend), which
> a host-process backend can't resolve. No-docker mode sets `AGENTEX_ACP_HOST_OVERRIDE=127.0.0.1`
> and the backend rewrites `host.docker.internal` → that value when dialing agents
> (`src/utils/acp_url.py`, applied in the ACP request path + Temporal healthcheck), so
> default-scaffolded agents work without manifest edits.

**Then in a separate terminal - Agent Development:**
```bash
agentex init # Create a new agent
Expand Down
48 changes: 41 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,37 +105,71 @@ To do this, you just need to spin up the [Agentex Server](https://github.com/sca

### Quick Start (Recommended)

Just run one command:
Just run one command — no Docker required:

```bash
./dev.sh
./dev.sh no-docker
```

That's it. This will automatically:
- Install Homebrew, uv, Node.js, and agentex-sdk if missing (macOS)
- Install all backend and frontend dependencies
- Start all Docker services (Postgres, Redis, MongoDB, Temporal)
- Start the backend API and frontend dev server
- Start the backend API and frontend dev server as host processes
- Provision embedded datastores — bundled Postgres + Redis, an auto-downloaded Temporal
dev server, a local MongoDB, and an optional OTel collector
- Wait for everything to be healthy

> **Note:** Make sure Docker Desktop or Rancher Desktop is running before you start.
> Prefer containers? `./dev.sh` (or `./dev.sh docker`) runs the same stack with Docker
> instead (needs Docker Desktop or Rancher Desktop) — see [Other commands](#other-commands)
> below. See [Docker-free mode](#docker-free-mode) for `no-docker` flags and details.

Once ready:
| Service | URL |
|---------|-----|
| Frontend UI | http://localhost:3000 |
| Backend API | http://localhost:5003 |
| Swagger Docs | http://localhost:5003/swagger |
| Temporal UI | http://localhost:8080 |
| Temporal UI | http://localhost:8233 |

**Other commands:**
> With `./dev.sh` (Docker) the Temporal UI is on http://localhost:8080 instead.

#### Other commands
```bash
./dev.sh # Start everything with Docker instead (containers; needs Docker Desktop/Rancher)
./dev.sh stop # Stop all services
./dev.sh status # Check service status
./dev.sh logs # View all logs
./dev.sh restart # Restart all services
```

#### Docker-free mode

`./dev.sh no-docker` accepts flags to trim the stack:

```bash
./dev.sh no-docker # whole stack, no Docker
./dev.sh no-docker --lean # Postgres + Redis + API + MongoDB only (no Temporal/OTel)
./dev.sh no-docker --no-temporal # skip Temporal + the worker
./dev.sh no-docker --mongo-uri <uri> # use an external MongoDB instead of a local mongod
```

> **MongoDB is required for the full no-docker stack** and is always started. The Temporal
> worker needs it, so `./dev.sh no-docker` auto-installs `mongod` (via Homebrew) and startup
> **fails fast** with an install message if it can't be made available. Point at an
> existing MongoDB with `--mongo-uri <uri>` to skip the local `mongod`. The OTel
> collector is optional; if it's absent the runner continues without telemetry. In
> no-docker mode the Temporal UI is at http://localhost:8233 (not :8080). Same `stop` / `status` /
> `logs` / `restart` commands apply.

**Connecting agents in no-docker mode.** Agents scaffolded by `agentex init` register their
ACP URL as `http://host.docker.internal:<port>` (so a *Docker* backend can reach an
agent on the host). A host-process backend can't resolve that name, so no-docker mode sets
`AGENTEX_ACP_HOST_OVERRIDE=127.0.0.1` and the backend automatically rewrites
`host.docker.internal` → `127.0.0.1` when dialing agents (and their healthchecks). So a
default-scaffolded agent works with `./dev.sh no-docker` **without editing its manifest**.
(You can still set `local_development.agent.host_address: localhost` in the manifest if
you prefer; both work.)

Then skip ahead to [Create Your First Agent](#create-your-first-agent).

---
Expand Down
4 changes: 3 additions & 1 deletion agentex/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,6 @@ next-env.d.ts

.codeartifact-pip-conf

docs/site/
docs/site/

.dev-nodocker/
10 changes: 10 additions & 0 deletions agentex/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,19 @@ dev: install-dev ## Start development server with Docker Compose
@echo "🚀 Starting development server with Docker Compose..."
docker compose up --build

dev-no-docker: install-dev ## Start development server locally (no Docker)
@echo "🚀 Starting development server locally without Docker..."
@echo "ℹ️ MongoDB is REQUIRED for the full stack. If 'mongod' is not on your PATH,"
@echo " install it (brew tap mongodb/brew && brew install mongodb-community) or point"
@echo " at an external one with ARGS=\"--mongo-uri <uri>\". (Unlike './dev.sh no-docker',"
@echo " make does not auto-install it.)"
uv sync --group dev --group dev-no-docker
uv run python -m scripts.dev_nodocker $(ARGS)

dev-stop: ## Stop development server
@echo "Stopping dev server"
docker compose down
# TODO: Add support for stopping local dev server

dev-wipe: ## Stop dev server and wipe DB
@echo "Stopping dev server and wiping DB"
Expand Down
11 changes: 11 additions & 0 deletions agentex/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ dev = [
"vulture>=2.14",
"ruff>=0.3.4",
]
dev-no-docker = [
"pgserver>=0.1.4",
"redislite>=6.2.912183",
# SQLAlchemy's async engine needs greenlet at runtime. SQLAlchemy auto-installs
# it on linux x86_64 (docker/prod) but NOT on macOS arm64, so the local runner
# must pull it explicitly or /readyz and engine teardown fail.
"greenlet>=3.2.3",
]
test = [
"pytest>=8.3.3,<9",
"pytest-asyncio>=1.0.0,<2",
Expand All @@ -52,6 +60,9 @@ test = [
"factory-boy>=3.3.0,<4", # for test data factories
"greenlet>=3.2.3",
"asyncpg>=0.29.0",
# Embedded datastores for dev_nodocker tests (no testcontainers/docker needed)
"pgserver>=0.1.4",
"redislite>=6.2.912183",
]

[tool.hatch.build.targets.sdist]
Expand Down
50 changes: 50 additions & 0 deletions agentex/scripts/dev_nodocker/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""Run the agentex backend locally as host processes, with no Docker.

The engine behind `./dev.sh no-docker` / `make dev-no-docker`: it provisions embedded datastores,
runs migrations, and supervises uvicorn (plus a Temporal worker), tearing everything down
on Ctrl-C / SIGTERM. Postgres/Redis/Temporal need no system install (bundled /
auto-downloaded). MongoDB is REQUIRED for the full stack — the Temporal worker builds
Mongo-backed repositories at boot, so a missing/unreachable mongod fails fast instead of
crashing the worker. It is always started; --mongo-uri points at an external MongoDB
instead of launching a local mongod. The OTel collector is optional; --lean turns off
temporal/otel (but keeps MongoDB).

Modules: `config` (pure, unit-testable), `services` (provisioning), `supervise`
(subprocess plumbing), `runner` (orchestration).
"""

from scripts.dev_nodocker.config import (
LOOPBACK,
DevNoDockerConfig,
build_arg_parser,
build_env,
resolve_config,
)
from scripts.dev_nodocker.runner import main, run
from scripts.dev_nodocker.services import (
provision_mongo,
provision_otel,
provision_postgres,
provision_redis,
provision_temporal,
teardown_redis,
)
from scripts.dev_nodocker.supervise import run_migrations, wait_for_health

__all__ = [
"LOOPBACK",
"DevNoDockerConfig",
"build_arg_parser",
"resolve_config",
"build_env",
"provision_postgres",
"provision_redis",
"provision_temporal",
"provision_mongo",
"provision_otel",
"teardown_redis",
"run_migrations",
"wait_for_health",
"run",
"main",
]
6 changes: 6 additions & 0 deletions agentex/scripts/dev_nodocker/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"""Entry point: `python -m scripts.dev_nodocker` (used by `./dev.sh no-docker` / `make dev-no-docker`)."""

from scripts.dev_nodocker.runner import main

if __name__ == "__main__":
main()
Loading