Configuration
Your entire gateway is one YAML file (or a few, if you split it up). Here’s every top-level key you can set and what it does.
Minimal config
Section titled “Minimal config”version: "1.0.0"proxy: expose: - name: hello.echo executor: { kind: noop }That’s a valid config. Everything except version is optional. You add keys as you need them.
version
Section titled “version”Required, non-empty string.
version: "1.0.0""1.0.0" is the current convention. The value isn’t parsed as semver or checked against a fixed list — any non-empty string is accepted — but it gives the gateway a hook to detect and migrate config formats as the schema evolves.
include
Section titled “include”Merge other YAML files into this config before the gateway starts. Maps merge (later wins on key collisions), arrays concatenate.
include: - ./connections.yaml - ./workflows/deploy.yaml - ./workflows/review.yamlPaths are relative to the main config file. This is useful for splitting a large config across teams or environments — keep shared connections in one file, team-specific workflows in another.
An entry can also be an object { uri, hash } for remote or verified includes:
include: - ./connections.yaml - { uri: "file:///etc/flowgate/shared.yaml" } - { uri: "https://example.com/policy.yaml", hash: "sha256:..." }Supported schemes are file://, https://, and git+https://. Any non-file:// URI requires a hash (sha256) so the merged config is reproducible and tamper-evident; the gateway refuses to merge if the fetched body doesn’t match.
Pull in versioned resource repos — shared collections of capabilities, orchestrators, skills, and scripts that live in their own directory with a flowgate.repo.yaml manifest at the root. This is the primary composition mechanism: instead of copying definitions between configs, you reference a repo and its definitions are merged into your gateway registry at load time.
repos: - path: ~/repos/cognitive-architectures - path: ../flowgate-metaEach entry is an object with a path field pointing at the repo directory. Relative paths resolve against the host config’s directory (the same convention as include:), and a leading ~/ expands to your home directory.
Every definition loaded from a repo is namespace-prefixed with the repo’s declared namespace — a repo whose manifest declares namespace: cognitive surfaces its ids as cognitive/<id> (e.g. cognitive/flow.add-feature). Two declared repos that share a namespace fail at config load (DUPLICATE_REPO_NAMESPACE).
The repo’s flowgate.repo.yaml manifest must declare schema: flowgate.repo/v1, a name, a namespace, and a version, plus an optional layout mapping the directories where each tier lives (defaults: capabilities/, orchestrators/, skills/, scripts/, connections/).
overrides
Section titled “overrides”When a repo provides a definition and your host config defines an id that collides with it, you must explicitly acknowledge the shadowing by listing the fully-qualified id in the top-level overrides: array. This closes a supply-chain backdoor: an operator can’t silently shadow a vendored definition.
overrides: - cognitive/cap.plan.vetoverrides: is an array of fully-qualified (namespace-prefixed) id strings. With the override declared, your host definition wins the collision. The gateway errors if you shadow a repo-provided id without listing it (ANONYMOUS_OVERRIDE), or if you list an id that no declared repo actually provides (STALE_OVERRIDE).
capabilities
Section titled “capabilities”Named, reusable capability definitions. You define a capability once here, then reference it from proxy.expose or from workflow transition executors.
capabilities: github.list_issues: title: List GitHub issues description: List issues from a GitHub repository. tags: [github, issues] inputSchema: type: object required: [repo] properties: repo: { type: string } additionalProperties: false executor: kind: mcp connection: github tool: list_issues guards: - { kind: role, role: developer } reliability: timeoutMs: 30000 retry: maxAttempts: 2 backoff: fixed initialDelayMs: 1000You can also wrap another capability to add guards or reliability on top:
capabilities: github.list_issues.safe: wraps: github.list_issues guards: - { kind: permission, permission: github.read }The wrapper inherits the wrapped capability’s executor and stacks its own guards and reliability on top.
connections
Section titled “connections”Named MCP server connections. The gateway speaks to these at runtime. Three kinds:
MCP connection (stdio)
Section titled “MCP connection (stdio)”connections: github: kind: mcp command: github-mcp-server args: [] env: GITHUB_TOKEN: "${GITHUB_TOKEN}"The gateway launches this as a child process and speaks MCP over stdio. Works with any MCP server — native binaries, npx shims, uvx launchers, Docker containers.
connections: filesystem: kind: mcp command: npx args: [-y, "@modelcontextprotocol/server-filesystem", "/tmp"]MCP connection (HTTP)
Section titled “MCP connection (HTTP)”If you provide url instead of command, the gateway connects to a running MCP server over the Streamable HTTP transport:
connections: remote_server: kind: mcp url: https://mcp.example.com/mcpWhen both url and command are set, url wins — a URL implies a hosted server rather than a process to launch.
CLI connection
Section titled “CLI connection”connections: dotnet: kind: cli command: dotnet workingDirectory: /path/to/project env: DOTNET_ENV: productionUsed with the cli executor. The gateway runs shell commands through this connection.
REST connection
Section titled “REST connection”connections: payroll: kind: rest baseUrl: https://payroll.example.com headers: Authorization: "Bearer ${PAYROLL_TOKEN}"Used with the rest executor. Headers defined here apply to every request through this connection.
The proxy section defines what capabilities the gateway exposes to the model. Two mechanisms: expose (define inline or reference capabilities) and import (auto-import from MCP connections).
proxy.expose
Section titled “proxy.expose”Each entry is either an inline definition or a reference to a named capability.
Inline definition — you define everything right here:
proxy: expose: - name: github.list_issues title: List GitHub issues description: List issues from a GitHub repository. tags: [github, issues, read] aliases: [gh-issues, list-issues] examples: - "List all open issues in the main repo" inputSchema: type: object required: [repo] properties: repo: { type: string } additionalProperties: false executor: kind: mcp connection: github tool: list_issues guards: - { kind: role, role: developer } reliability: timeoutMs: 30000Capability reference — point to a named capability:
proxy: expose: - capability: github.list_issues as: issues.list # optional: rename for the proxy description: Override description if you want tags: [extra-tag] # merged with the capability's tags aliases: [find-issues] # search synonyms guards: # stacked on top of the capability's guards - { kind: permission, permission: repo.read }proxy.import
Section titled “proxy.import”Auto-import tools from a connected MCP server. The gateway calls tools/list on the connection at startup and creates a proxy exposure for each tool.
proxy: import: - connection: github prefix: github # tools become github.list_issues, github.create_issue, etc. include: [list_issues, create_issue] # only these tools (omit for all) exclude: [delete_repo] # skip these tools tags: [github, source-control] # applied to all imported toolsYou can mix imports with explicit declarations. Declared capabilities can carry guards and reliability that imports don’t have by default.
workflows
Section titled “workflows”Multi-state workflow definitions. Each workflow is a state machine with states, transitions, guards, and executors.
workflows: deploy_pipeline: description: Lint, test, build, and deploy a service. tags: [deploy, pipeline] aliases: [ship, release] examples: - "Deploy the payments service to staging"
inputSchema: type: object required: [service] properties: service: { type: string } environment: type: string enum: [staging, production] default: staging additionalProperties: false
initialState: lint initialContext: # seed values for workflow context attempts: 0 maxChainDepth: 10 # max deterministic transitions before halting (default: 50) timeoutMs: 3600000 # workflow-level timeout (1 hour) linkFilter: all # "all" or "byGuards" — controls which transitions appear as links
onTimeout: # what happens if the workflow times out target: failed executor: kind: mcp connection: notifier tool: send_alert
states: lint: goal: Validate code quality guidance: This step runs automatically. transitions: run_lint: title: Run linter target: test actor: deterministic # runs automatically, no model decision executor: kind: cli command: lint-check args: ["$.input.service"] output: lintPassed: "$.output.json.passed"
test: transitions: run_tests: title: Run test suite target: ready_to_deploy actor: deterministic executor: kind: cli command: test-runner output: testsPassed: "$.output.json.passed"
ready_to_deploy: linkFilter: byGuards # per-state override — only show transitions whose guards pass transitions: deploy: title: Deploy to environment target: deployed actor: agent guards: - { kind: expr, expr: "$.context.testsPassed == true" } executor: kind: cli command: deploy args: ["$.context.artifactId"] output: deploymentId: "$.output.json.deploymentId" reliability: timeoutMs: 60000 retry: maxAttempts: 3 backoff: exponential initialDelayMs: 2000
abort: title: Abort deployment target: aborted
deployed: terminal: true
aborted: terminal: true
failed: terminal: trueTransition details
Section titled “Transition details”Each transition supports:
| Key | Purpose |
|---|---|
target | Destination state (required) |
title | Human-readable name, shown in links |
description | Longer explanation |
actor | Who can trigger: agent, human, system, deterministic (default: agent) |
inputSchema | JSON Schema for transition arguments |
guards | Array of guards that must all pass |
executor | What runs when the transition fires (see executors) |
output | Maps executor output into workflow context |
evidence | Requires specific evidence artifacts |
reliability | Timeout, retry, and fallback policies |
prefill | Pre-resolved argument values for links, reducing what the model has to generate |
branches | Auto-branch destination based on executor result (first matching when guard wins, otherwise falls back to target) |
Actor types
Section titled “Actor types”| Actor | Behavior |
|---|---|
agent | Default. The model decides when to take this transition. |
human | Only a human principal can submit. The gateway rejects agent submissions with ACTOR_MISMATCH. |
system | Reserved for system-triggered transitions. |
deterministic | The runtime chains through this automatically — no model decision needed. Multiple deterministic transitions execute in a single round trip. |
Controls where audit events go. Every workflow action emits structured JSON events automatically.
audit: sink: stderr # stderr | file | memory | none path: ./audit-logs # required when sink is "file" — a DIRECTORY rotation: daily # hourly | daily | weekly (default: daily)When sink: file, path is a directory of date-rotated log files, not a single .jsonl. The rotation key controls how often a new file is started (hourly, daily, or weekly); it defaults to daily.
See audit events for the full event reference.
discovery
Section titled “discovery”Controls what gets indexed for search.
discovery: include: # what to index (default: ["proxy", "workflows"]) - proxy # proxy capabilities (default: included) - workflows # workflow definitions (default: included) - connections # raw connections (default: not included)include is the only honored key. By default, proxy capabilities and workflows are indexed. Add connections if you want raw connections to appear in search results too. An unrecognized token (e.g. workflow instead of workflows) fails the config with INVALID_DISCOVERY_INCLUDE rather than silently dropping a category.
Where workflow instances are persisted. See stores for the full reference.
store: kind: memory # memory | file | sqlite path: ./workflows.db # filesystem path — used by file and sqlitepath is the filesystem location for file (a directory) and sqlite (a database file); memory ignores it. Only sqlite keeps Evidence and acknowledgment stores durable. A serve deployment refuses kind: file (it would lose governance state on restart) unless gateway.allow_ephemeral: true is set for dev.
embeddings
Section titled “embeddings”Optional. Enables semantic candidate ranking for lexicon SUBJECT_NEEDS_DEFINITION interactions (SPEC §30.10.10). Omit the block entirely (or set backend: none) to use lexical-only ranking.
embeddings: backend: ollama # none (default) | ollama | openai_compatible url: http://localhost:11434/api/embeddings # required when backend != none model: nomic-embed-text # provider's model name dimensions: 768 # required (>0) when backend != none api_key_env: OPENROUTER_API_KEY # optional; absent for unauthenticated local servicesWhen a backend other than none is set, the gateway POSTs to the configured URL at lexicon-write time to compute embeddings, and at SUBJECT_NEEDS_DEFINITION time to rank candidates semantically. ollama and openai_compatible select the request/response format. On backend failure, lexicon writes are rejected with EMBEDDING_BACKEND_FAILED. See Lexicon and Discovery for the tiered ranking details.