Manifest Schema
The .eve/manifest.yaml file is the single source of truth for how an Eve Horizon project builds, deploys, and runs. It uses Docker Compose-style service definitions extended with Eve-specific fields under x-eve.
The current schema identifier is eve/compose/v2. Unknown fields are allowed for forward compatibility.
Minimal Example
schema: eve/compose/v2
project: my-project
registry:
host: public.ecr.aws/w7c4v0w3
namespace: eve-horizon
auth:
username_secret: REGISTRY_USERNAME
token_secret: REGISTRY_PASSWORD
services:
db:
image: postgres:16
ports: [5432]
environment:
POSTGRES_DB: app
POSTGRES_USER: app
POSTGRES_PASSWORD: ${secret.DB_PASSWORD}
healthcheck:
test: ["CMD", "pg_isready", "-U", "app"]
interval: 5s
timeout: 3s
retries: 5
api:
build:
context: ./apps/api
ports: [3000]
environment:
DATABASE_URL: postgres://app:${secret.DB_PASSWORD}@db:5432/app
depends_on:
db:
condition: service_healthy
x-eve:
ingress:
public: true
port: 3000
api_spec:
type: openapi
spec_url: /openapi.json
environments:
test:
pipeline: deploy-test
pipelines:
deploy-test:
steps:
- name: migrate
action: { type: job, service: migrate }
- name: deploy
depends_on: [migrate]
action: { type: deploy }
Top-Level Fields
| Field | Required | Type | Description |
|---|---|---|---|
schema | No | string | Schema identifier, e.g., eve/compose/v2 |
project | No | string | Human-friendly project slug (informational) |
registry | No | object | "eve" | "none" | Container registry configuration |
services | Yes | map<string, Service> | Compose-style service definitions |
environments | No | map<string, Environment> | Environment definitions and overrides |
pipelines | No | map<string, Pipeline> | Deterministic step-based pipelines |
workflows | No | map<string, Workflow> | On-demand workflow definitions |
versioning | No | object | Release/version policy (semver, tagging) |
x-eve | No | object | Eve-specific top-level extensions |
Services
Services follow Docker Compose conventions. Each key under services is a service name.
Service Fields
| Field | Type | Description |
|---|---|---|
image | string | Base image (tag optional -- Eve tags at build time) |
build | object | Build configuration |
build.context | string | Build context directory (required if build is set) |
build.dockerfile | string | Dockerfile path relative to context |
build.args | map<string, string> | Build-time arguments |
environment | map<string, string> | Environment variable map |
ports | array<string | number> | Container ports (Compose-style entries) |
depends_on | map<string, object> | Dependency ordering with health conditions |
healthcheck | object | Docker-style health check |
command | string | array | Override the container command |
volumes | array<string> | Volume mounts (Compose syntax) |
x-eve | object | Eve extensions (see below) |
Dependency Conditions
depends_on:
db:
condition: service_healthy
Supported values: service_started (alias: started), service_healthy (alias: healthy).
Health Checks
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 10s
timeout: 5s
retries: 3
start_period: 10s
All timing fields are optional duration strings (e.g., 5s, 10s).
Service x-eve Extensions
Each service may include an x-eve block (or x_eve in code) for Eve-specific behavior.
| Field | Type | Description |
|---|---|---|
role | string | component (default), worker, job, or managed_db |
ingress | object | Public routing configuration |
ingress.public | boolean | Enable public ingress (default: true when ports are exposed) |
ingress.port | number | Port to route traffic to |
ingress.alias | string | Custom subdomain alias (3-63 chars, lowercase alphanumeric + hyphens) |
ingress.domain | string | Override domain used for ingress hostname generation |
api_spec | object | Single API spec registration |
api_specs | array<ApiSpec> | Multiple API spec registrations |
external | boolean | If true, service is not deployed (external dependency) |
url | string | Connection string for external services |
worker_type | string | Worker pool type for worker-role services |
files | array<FileMount> | Mount repo files into the container |
storage | object | Persistent volume configuration |
managed | object | Managed database config (requires role: managed_db) |
Roles
component(default) -- a long-running service deployed to Kubernetes.worker-- a background worker service.job-- a one-off container (migrations, seeds) runnable as a pipeline step.managed_db-- a platform-provisioned database (not deployed to Kubernetes).
API Spec Registration
x-eve:
api_spec:
type: openapi # openapi | postgrest | graphql
spec_path: /app/openapi.json
# or spec_url: /openapi.json
on_deploy: true # refresh spec after each deploy (default: true)
auth: eve # eve | none (default: eve)
name: my-api # optional display name
spec_url may be relative (resolved against the service URL) or absolute.
spec_path is resolved against the container filesystem.
File Mounts
x-eve:
files:
- source: ./config/app.conf # relative path in repo
target: /etc/app/app.conf # absolute path in container
Persistent Storage
x-eve:
storage:
name: app-data
mount_path: /data
size: 10Gi
access_mode: ReadWriteOnce # ReadWriteOnce | ReadWriteMany | ReadOnlyMany
storage_class: standard
Managed Databases
Services with role: managed_db are provisioned by the platform, not deployed to Kubernetes.
services:
db:
x-eve:
role: managed_db
managed:
class: db.p1 # tier: db.p1, db.p2, db.p3
engine: postgres # only postgres currently supported
engine_version: "16"
- Provisioning happens on first deploy for an environment.
- Use
eve db status --env <name>to view provisioning state. - Other services reference managed values with
${managed.<service>.<field>}placeholders (resolved at deploy time).
Environments
Environments link pipelines to deploy targets and support per-environment overrides.
environments:
staging:
pipeline: deploy
pipeline_inputs:
smoke_test: true
timeout: 1800
approval: required
overrides:
services:
api:
environment:
NODE_ENV: staging
workers:
- type: default
service: worker
replicas: 2
| Field | Type | Description |
|---|---|---|
pipeline | string | Pipeline to run when deploying this environment |
pipeline_inputs | map<string, any> | Default inputs for the pipeline run (merged with CLI --inputs, CLI wins) |
approval | string | Set to required to gate deploy and job steps |
type | string | Environment lifecycle: persistent or temporary |
kind | string | Environment taxonomy: standard or preview |
labels | array<string> | Metadata labels for filtering and UIs |
overrides | object | Compose-style service overrides for this environment |
overrides.services | map<string, Service> | Per-service environment/config overrides |
workers | array<object> | Worker pool selection for this environment |
Environment Pipeline Behavior
When pipeline is set, eve env deploy <env> triggers a pipeline run instead of a direct deployment. This enables consistent build/test/deploy workflows and promotion patterns.
To bypass the pipeline and perform a direct deployment:
eve env deploy staging --ref <sha> --direct
Promotion Pattern
environments:
test:
pipeline: deploy-test
staging:
pipeline: deploy
pipeline_inputs:
smoke_test: true
production:
pipeline: deploy
approval: required
# Build + test + release in test
eve env deploy test --ref <sha>
# Promote to staging (reuse release)
eve release resolve v1.2.3
eve env deploy staging --ref <sha> --inputs '{"release_id":"rel_xxx"}'
# Promote to production (approval gate)
eve env deploy production --ref <sha> --inputs '{"release_id":"rel_xxx"}'
Triggers
Pipelines and workflows can be triggered automatically via events from GitHub, Slack, the system, or cron schedules.
Triggers are declared under:
pipelines.<name>.triggerworkflows.<name>.trigger
GitHub push trigger
pipelines:
ci-cd-main:
trigger:
github:
event: push
branch: main
GitHub pull request trigger
pipelines:
ci-cd-main:
trigger:
github:
event: pull_request
action: [opened, synchronize, reopened]
base_branch: main
Slack trigger
workflows:
support:
trigger:
slack:
event: app_mention
channel: C123ABC
System trigger
pipelines:
remediation:
trigger:
system:
event: job.failed
pipeline: deploy
Cron and manual triggers
workflows:
log-audit:
trigger:
cron:
schedule: "0 */6 * * *"
workflows:
manual-release:
trigger:
manual: true
Use these rules on both pipelines and workflows when you want automation, remediation, or scheduled maintenance.
Pipelines
Pipelines define deterministic step graphs that expand into job graphs at runtime.
pipelines:
deploy:
steps:
- name: build
action: { type: build }
- name: unit-tests
script:
run: "pnpm test"
timeout: 1800
- name: release
depends_on: [build, unit-tests]
action: { type: release }
- name: deploy
depends_on: [release]
action: { type: deploy }
Step Types
Each step is one of the following:
| Type | Field | Description |
|---|---|---|
| action | action.type | Built-in action: build, release, deploy, run, job, create-pr |
| script | script.run | Shell command executed by the worker |
| agent | agent.prompt | AI agent job with an optional config block |
| run | run | Shorthand for script.run |
Step Fields
| Field | Type | Description |
|---|---|---|
name | string | Step identifier (unique within pipeline) |
depends_on | array<string> | Step names that must complete before this step runs |
action | object | Built-in action configuration |
action.type | string | Built-in action name (build, release, deploy, run, job, create-pr, notify, env-ensure, env-delete) |
action.with | object | Action-specific parameters |
script | object | Script execution (run, command, timeout) |
agent | object | AI agent job (prompt, optional config) |
run | string | Shorthand for script.run |
requires | object | Step-level requirements |
requires.secrets | array<string> | Secrets required by this step (validated during sync) |
Action Types
| Action | Description |
|---|---|
build | Build container images for services with build config |
release | Create a tagged release from build artifacts |
deploy | Deploy services to the target environment |
run | Run a one-off container |
job | Execute a service marked as role: job (e.g., migrations) |
create-pr | Create a pull request from job changes |
notify | Send a notification when the step completes |
env-ensure | Ensure an environment exists and is ready |
env-delete | Delete a managed environment and optional resources |
Action input fields
| Action | Key | Purpose |
|---|---|---|
deploy | env_name | Target environment for the deployment |
job | service | Run a x-eve.role: job service |
create-pr | title, body, branch | PR metadata |
notify | channel, message | Notification destination and message |
env-ensure | env_name, kind | Create environment if missing (standard or preview) |
env-delete | env_name | Delete environment |
Workflows
Workflows are manifest-defined jobs stored and returned as-is. The platform extracts db_access when present.
Use the optional hints block to set workflow-level defaults (for example timeout, worker type, or gates).
workflows:
nightly-audit:
db_access: read_only
hints:
worker_type: default-worker
steps:
- agent:
prompt: "Audit errors and summarize anomalies"
Invoke workflows with the CLI:
eve workflow run nightly-audit --input '{"scope":"last-24h"}'
eve workflow invoke nightly-audit # run and wait for result
Registry
The registry field configures container image storage.
Object Form
registry:
host: public.ecr.aws/w7c4v0w3
namespace: eve-horizon
auth:
username_secret: REGISTRY_USERNAME
token_secret: REGISTRY_PASSWORD
| Field | Type | Description |
|---|---|---|
host | string | Registry hostname |
namespace | string | Image namespace/prefix |
auth.username_secret | string | Secret name for registry username |
auth.token_secret | string | Secret name for registry password/token |
The deployer uses these secrets to create Kubernetes imagePullSecrets.
String Form
registry: "eve" # Use Eve-native registry (internal, JWT-based auth)
registry: "none" # Opt out of registry auth (public images or external auth)
x-eve.defaults
Default settings for jobs created in this project. Merged on job creation; explicit job fields override defaults.
x-eve:
defaults:
env: staging
harness_preference:
harness: mclaude
profile: primary-orchestrator
options:
model: opus-4.5
reasoning_effort: high
hints:
permission_policy: auto_edit
resource_class: job.c1
max_cost:
currency: usd
amount: 5
max_tokens: 200000
git:
ref_policy: auto
branch: job/${job_id}
create_branch: if_missing
commit: manual
push: never
workspace:
mode: job
| Field | Type | Description |
|---|---|---|
env | string | Default target environment for jobs |
harness_preference | object | Preferred harness defaults; replaces legacy harness / harness_profile / harness_options |
harness | string | Deprecated. Use harness_preference.harness. |
harness_profile | string | Deprecated. Use harness_preference.profile. |
harness_options | object | Deprecated. Use harness_preference.options. |
hints | object | Deprecated. Legacy job-hints fields retained for compatibility. |
git | object | Default git controls (see Job API -- Git Controls) |
workspace | object | Default workspace configuration |
harness, harness_profile, and harness_options are legacy fields and map to harness_preference.
hints at this level is also legacy; prefer inline profile preferences or explicit agent-level hints.
x-eve.agents
Define per-project agent profiles and councils for orchestration.
x-eve:
agents:
version: 1
availability:
drop_unavailable: true
profiles:
primary-orchestrator:
- harness: mclaude
model: opus-4.5
reasoning_effort: high
primary-reviewer:
- harness: mclaude
model: opus-4.5
reasoning_effort: high
- harness: codex
model: gpt-5.2-codex
reasoning_effort: x-high
planning-council:
- profile: primary-planner
- harness: gemini
model: gemini-3
Each profile is an ordered array of harness/model candidates. The orchestrator selects the first available candidate, or runs councils in parallel.
The manifest sync API returns parsed agent config as parsed_agents, consumed by orchestrators via eve agents config.
Pack overlay removals
Use _remove: true in an override object to drop a value introduced by a pack:
agents:
stale-pack-agent:
_remove: true
This keeps a local manifest authoritative by explicitly removing inherited values instead of silently merging.
x-eve.packs
AgentPacks import agent, team, chat, and skills configuration from external repositories.
x-eve:
# Default agents to install skills for (defaults to [claude-code])
install_agents: [claude-code, codex, gemini-cli]
packs:
# Local pack
- source: ./skillpacks/my-pack
# Remote pack (ref required for remote sources)
- source: incept5/eve-skillpacks
ref: 0123456789abcdef0123456789abcdef01234567
packs: [eve-work, eve-se]
# Per-pack agent override
- source: ./skillpacks/claude-only
install_agents: [claude-code]
| Field | Type | Description |
|---|---|---|
source | string | Local path, owner/repo, github:owner/repo, or git URL |
ref | string | 40-character SHA (required for remote sources) |
packs | array<string> | Optional subset of remote pack namespaces to install |
install_agents | array<string> | Override which agents receive this pack's skills |
Pack refs and subset filters follow the same form shown above: source identifies the pack source, ref pins the version, and optional packs limits which named pack groups are installed.
Packs are resolved by eve agents sync and locked in .eve/packs.lock.yaml. Use eve packs status to check lockfile state and drift.
x-eve.requires
Declare required secrets for validation during manifest sync.
x-eve:
requires:
secrets: [GITHUB_TOKEN, REGISTRY_TOKEN]
Pipeline steps can also declare per-step secret requirements:
pipelines:
ci:
steps:
- name: integration-tests
script:
run: "pnpm test"
requires:
secrets: [DATABASE_URL]
Validate with:
eve project sync --validate-secrets # validate during sync
eve project sync --strict # fail on missing secrets
eve manifest validate # pre-flight check without syncing
Platform-Injected Environment Variables
Eve automatically injects these variables into all deployed services:
| Variable | Description |
|---|---|
EVE_API_URL | Internal cluster URL for server-to-server calls (e.g., http://eve-api:4701) |
EVE_PUBLIC_API_URL | Public ingress URL for browser-facing apps (e.g., https://api.eh1.incept5.dev) |
EVE_PROJECT_ID | The project ID (e.g., proj_01abc123...) |
EVE_ORG_ID | The organization ID (e.g., org_01xyz789...) |
EVE_ENV_NAME | The environment name (e.g., staging, production) |
Use EVE_API_URL for backend/server-side calls within the cluster. Use EVE_PUBLIC_API_URL for browser or external calls.
Job runners additionally receive EVE_ENV_NAMESPACE, EVE_JOB_ID, EVE_ATTEMPT_ID, EVE_AGENT_ID, and EVE_PARENT_JOB_ID.
Services can override any of these by defining them explicitly in their environment section.
Secret Interpolation
Reference secrets in environment values with the ${secret.<KEY>} syntax:
environment:
DATABASE_URL: postgres://app:${secret.DB_PASSWORD}@db:5432/app
API_KEY: ${secret.THIRD_PARTY_API_KEY}
Secrets are resolved at deploy time from the project's secret store. They are never written to the manifest or exposed in logs.
Variable Interpolation
Environment values support variable interpolation for deploy-time context:
| Variable | Description |
|---|---|
${ENV_NAME} | Current environment name |
${PROJECT_ID} | Project ID |
${ORG_ID} | Organization ID |
${COMPONENT_NAME} | Service/component name |
${ORG_SLUG} | Organization slug |
Example:
environment:
POSTGRES_DB: app_${ENV_NAME}
LOG_PREFIX: ${PROJECT_ID}/${ENV_NAME}
Managed Database Placeholders
When a service depends on a managed database, reference provisioned values with ${managed.<service>.<field>}:
environment:
DATABASE_URL: ${managed.db.url}
These placeholders are resolved at deploy time once the managed database is provisioned.
See Also
- CLI Commands --
eve project sync,eve manifest validate - Job API -- how
x-eve.defaultsmerges into job creation - Pipelines -- pipeline execution details
- Workflows -- workflow invocation patterns