dev-setup
Development & Test Environment Setup
This doc covers a local (non-Docker) setup for development and testing.
Prerequisites
- macOS or Linux
- Git
- Docker + Docker Compose (optional but recommended)
Haskell toolchain (local dev)
- Stack
- GHC (managed by Stack)
Protobuf toolchain (optional, for core codegen)
protocproto-lens-protocbuf(optional)
TLS/dev certs
openssl
Recommended setup (macOS with Homebrew)
brew install haskell-stack grpc protobuf buf opensslFor Haskell proto codegen:
stack install proto-lens-protocBuild
make buildGenerate protobuf modules
- Core only:
make proto-core- Runner only:
make proto-runner- Both:
make protoDev certs
make dev-certsOutputs:
- certs/dev/ca.{crt,key}
- certs/dev/server.{crt,key}
Local run
Runner
make runnerCLI
make cliWith CLI args:
make cli CLI_ARGS="--host 0.0.0.0 --port 50051"Docker-based dev
On‑prem stack:
cp deploy/.env.onprem.example deploy/.env.onprem
docker compose --env-file deploy/.env.onprem -f deploy/docker-compose.onprem.yml pull console
docker compose --env-file deploy/.env.onprem -f deploy/docker-compose.onprem.yml up --buildCloud stack:
cp deploy/cloud/.env.cloud.example deploy/cloud/.env.cloud
docker compose --env-file deploy/cloud/.env.cloud -f deploy/cloud/docker-compose.cloud.yml up --buildTear down:
make onprem-down
make cloud-downTests
Integration security smoke skeleton:
cp tests/integration/.env.integration.example tests/integration/.env.integration
set -a; source tests/integration/.env.integration; set +a
bash tests/integration/security_smoke.shLLM routing (dev)
Routing rules: - Tenant override takes priority - Otherwise: default chain with round-robin - Failover to next provider on error
Environment variables (example):
LLM_DEFAULT_CHAIN="internal,openai,anthropic,gemini,grok"
LLM_ROUND_ROBIN="true"
LLM_TENANT_OVERRIDE_TENANT_A="openai"
LLM_TENANT_OVERRIDE_TENANT_B="internal"Provider settings (OpenAI-compatible APIs):
LLM_PROVIDER_INTERNAL_BASE_URL="http://llm-gateway:8080"
LLM_PROVIDER_INTERNAL_MODEL="internal-default"
LLM_PROVIDER_OPENAI_API_KEY="sk-..."
LLM_PROVIDER_OPENAI_MODEL="gpt-4o-mini"
LLM_PROVIDER_ANTHROPIC_BASE_URL="https://api.anthropic.com"
LLM_PROVIDER_ANTHROPIC_MODEL="claude-3-5-sonnet-20240620"
LLM_PROVIDER_GEMINI_BASE_URL="https://generativelanguage.googleapis.com"
LLM_PROVIDER_GEMINI_MODEL="gemini-1.5-pro"
LLM_PROVIDER_GROK_BASE_URL="https://api.x.ai"
LLM_PROVIDER_GROK_MODEL="grok-2"LLM decision endpoint (core)
Core can call the LLM, enforce policy, and dispatch a job in one request:
curl -s -X POST http://localhost:8080/api/agent/llm-decide-and-dispatch \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"tenant_id":"default",
"runner_id":"runner-1",
"env":"prod",
"action_kind":"ActionShell",
"prompt":"Deploy failed on svc-a. Suggest next step.",
"approval": {
"channel":"slack",
"message":"Approve remediation for svc-a",
"execution_id":"exec-123",
"step_id":"step-1",
"approval_timeout_seconds": 3600
},
"job":{
"workflow_id":"wf-deploy",
"kind":{
"tag":"JobShell",
"contents":{
"command":"kubectl rollout undo deploy/svc-a",
"cwd":"/",
"shell_timeout_seconds": 300,
"allowlist_tag":"deploy"
}
}
}
}'Response example:
{
"llm_provider": "ProviderInternal",
"llm_decision": "LlmRequestApproval",
"llm_rationale": "Risky change in prod; approval recommended.",
"final_decision": "FinalApprovalRequired"
}Core can call the LLM and return recommendation only (no dispatch):
curl -s -X POST http://localhost:8080/api/agent/llm-recommend \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"tenant_id":"default",
"env":"prod",
"action_kind":"ActionShell",
"prompt":"Deploy failed on svc-a. Suggest next step.",
"job":{
"workflow_id":"wf-deploy",
"kind":{
"tag":"JobShell",
"contents":{
"command":"kubectl rollout undo deploy/svc-a",
"cwd":"/",
"shell_timeout_seconds": 300,
"allowlist_tag":"deploy"
}
}
}
}'Response example:
{
"llm_provider": "ProviderInternal",
"llm_decision": "LlmRequestApproval",
"llm_rationale": "Shell rollback in prod; approval required."
}DB step (Runner)
DB execution is driver-based and uses CLI tools:
- postgres → psql
- mysql → mysql
- sqlite → sqlite3
Configuration:
RUNNER_DB_DSN_TENANTDB="postgres://user:pass@host:5432/db"
RUNNER_DB_ALLOWLIST="TENANTDB,REPORTING"Notes:
- read_only=true blocks obvious write queries (INSERT/UPDATE/DELETE/CREATE/DROP/ALTER/REPLACE/TRUNCATE).