Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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