Local Development
This guide explains how to run AxonFlow locally for development, testing, and single-tenant deployments.
Prerequisites
| Dependency | Minimum Version | Notes |
|---|---|---|
| Go | 1.25+ | Required for building from source |
| Node.js | 18+ | Required for Customer Portal UI development |
| Docker | 24+ | Container runtime |
| Docker Compose | v2 | Compose V2 (the docker compose plugin, not standalone docker-compose) |
| Git | 2.30+ | Source control |
go version # go1.25 or higher
node --version # v18.x or higher
docker --version # Docker 24.x or higher
docker compose version # v2.x
Build from Source
If you want to build AxonFlow from source rather than using pre-built Docker images:
# Clone the repository
git clone https://github.com/getaxonflow/axonflow.git
cd axonflow
# Build all Go binaries
go build ./platform/...
# Run tests
go test ./platform/... -cover
# Start the full stack with Docker Compose
docker compose up
The docker compose up command builds images locally if they are not already cached. To force a rebuild after code changes:
docker compose up --build
SELF_HOSTED_MODE
For local development and single-tenant deployments, AxonFlow provides SELF_HOSTED_MODE which bypasses license validation entirely.
When to Use SELF_HOSTED_MODE
| Scenario | Use SELF_HOSTED_MODE? |
|---|---|
| Local development | Yes |
| Unit testing | Yes |
| Integration testing | Yes |
| Single-tenant internal deployment | Yes |
| Multi-tenant SaaS | No |
| Production with external clients | No |
Enabling SELF_HOSTED_MODE
Set the environment variable before starting AxonFlow:
export SELF_HOSTED_MODE=true
Or in your docker-compose.yml:
services:
agent:
environment:
- SELF_HOSTED_MODE=true
What Happens When Enabled
When SELF_HOSTED_MODE=true:
- License validation is skipped - No license key required
- All requests are allowed - No authentication needed
- Full connector access - All MCP connectors available
- No tenant isolation - All requests treated as same tenant
Quick Start with Docker Compose
# Clone AxonFlow
git clone https://github.com/getaxonflow/axonflow.git
cd axonflow
# Set API key for LLM features (optional)
export OPENAI_API_KEY=sk-your-key-here
# Start all services (SELF_HOSTED_MODE enabled by default)
docker compose up -d
# Check services are healthy
docker compose ps
# Test the agent health
curl http://localhost:8080/health
# Test the orchestrator health
curl http://localhost:8081/health
# Run the interactive demo
./examples/demo/demo.sh
# Access Grafana dashboards (optional)
open http://localhost:3001
The Docker Compose setup enables SELF_HOSTED_MODE by default, so you don't need to set it manually.
Services Available:
- Agent: http://localhost:8080
- Orchestrator: http://localhost:8081
- Grafana: http://localhost:3001
- Prometheus: http://localhost:9090
- PostgreSQL: localhost:5432
- Redis: localhost:6379
Security Considerations
SELF_HOSTED_MODE should only be used when:
- Running locally for development
- Running in a trusted network environment
- All applications connecting to AxonFlow are trusted
Never use in production multi-tenant environments -- use proper license keys instead.
Running Tests
With SELF_HOSTED_MODE enabled, you can run the full test suite:
# Run all tests
go test ./...
# Run with coverage
go test -cover ./...
# Run specific module
go test ./platform/agent/...
Hot Reload for Development
For faster iteration during Go development, use air to automatically rebuild and restart when source files change:
# Install air
go install github.com/air-verse/air@latest
# Run the agent with hot reload
cd platform/agent
air
Create an .air.toml configuration in the module directory to customize watched paths and build commands. This avoids manually stopping and restarting the service after every code change.
Local Architecture
┌──────────────────────────────────────────────────┐
│ Your Development Machine │
│ │
│ ┌─────────────────────────────────────────────┐ │
│ │ docker-compose │ │
│ │ │ │
│ │ ┌────────┐ ┌──────────────┐ ┌────────┐ │ │
│ │ │ Agent │◄►│ Orchestrator │◄►│ MCP │ │ │
│ │ │ :8080 │ │ :8081 │ │ │ │ │
│ │ └────────┘ └──────────────┘ └────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌───────────────────┐ │ │
│ │ │ PostgreSQL │ │ │
│ │ │ :5432 │ │ │
│ │ └───────────────────┘ │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ SELF_HOSTED_MODE=true │
│ (No license validation) │
└──────────────────────────────────────────────────┘
Transitioning to Production
When you're ready to move from local development to production:
- SaaS Multi-Tenant: Contact [email protected] for service licenses
- In-VPC Single-Tenant: Keep
SELF_HOSTED_MODEif all apps are trusted, or use licenses for external apps - AWS Marketplace: Follow the AWS Marketplace deployment guide
See the Enterprise License Management documentation for detailed licensing information.
Troubleshooting
"License validation failed" Error
If you see this error during local development:
License validation failed: license key required
Solution: Ensure SELF_HOSTED_MODE=true is set:
export SELF_HOSTED_MODE=true
# Then restart AxonFlow
Container Can't Connect to Database
If the agent can't connect to PostgreSQL:
# Check if PostgreSQL is running
docker compose ps
# View PostgreSQL logs
docker compose logs postgres
# Restart all services
docker compose down && docker compose up
Port Already in Use
If ports 8080, 8081, or 5432 are already in use:
# Find what's using the port
lsof -i :8080
# Kill the process if appropriate
kill -9 <PID>
# Or use different ports in docker-compose.yml
# ports:
# - "9080:8080" # Map to 9080 instead
Docker Out of Memory
If containers crash or become unresponsive, Docker may not have enough memory allocated:
# Check Docker resource usage
docker stats --no-stream
# Check Docker settings — allocate at least 8 GB RAM
# On Docker Desktop: Settings → Resources → Memory → 8.00 GB
AxonFlow's full stack (agent, orchestrator, PostgreSQL, Redis, Grafana, Prometheus) requires approximately 4-6 GB of memory. The default Docker Desktop allocation of 2 GB is insufficient.
Go Module Cache Issues
If go build or go test fails with module resolution errors after switching branches or updating dependencies:
# Clear the module download cache
go clean -modcache
# Re-download dependencies
go mod download
# Verify module graph
go mod verify
Orchestrator Connection Refused
If the agent starts but cannot reach the orchestrator:
# Verify orchestrator is running
curl http://localhost:8081/health
# Check orchestrator logs for startup errors
docker compose logs orchestrator
# Ensure both services are on the same Docker network
docker compose ps
The agent expects the orchestrator at the hostname orchestrator:8081 within the Docker network. If you are running services outside Docker, set ORCHESTRATOR_URL=http://localhost:8081 on the agent.
Contributing
See the Contributing Guide for development workflow, code style, testing requirements, and how to submit pull requests.
Next Steps
- Deployment Overview - Deploy to production
- Architecture Overview - Understand system design
- Policy Syntax - Write governance policies
