Skip to content
KortixKortix
Esc
navigateopen⌘Jpreview
On this page

Manifest reference

Every kortix.yaml v2 key, with defaults, limits, and validation rules.

The manifest is the file the platform treats as authoritative for a project. This page lists every kortix.yaml (v2) key, its type, its default, and how the platform validates it. For the plain-language version, see Your project.

Two configuration surfaces

A Kortix project has two configuration surfaces with strict, non-overlapping ownership.

  • Kortix configkortix.yaml at the repo root, plus .kortix/Dockerfile. The platform reads this: the trigger sweep, the sandbox builder, session token minting, and the dashboard.
  • OpenCode config — everything under .kortix/opencode/ (opencode.jsonc, agents/, skills/, commands/, tools/, plugins/). The OpenCode runtime reads this, in the sandbox and locally.

The join between the two halves is the agent name. A manifest key agents.<name> must match the filename .kortix/opencode/agents/<name>.md. Every behavioral field lives only in that .md file’s frontmatter and body, never in kortix.yaml:

  • system prompt
  • model, mode
  • temperature, top_p
  • steps, permission

The manifest’s agents: block sets governance only: which agents may launch, and what each one may touch. The validator enforces this. It rejects a v2 agent block that contains any behavioral field, with an error that points at the agent’s own .md file.

Location and versions

Any repo with a valid manifest at its root is a Kortix project. kortix.yaml (v2, YAML only) is the current format for new projects, created by the web “Create project” flow and by kortix init. kortix.toml (v1) still works for existing projects, but the platform accepts no new v2 features on it. See Legacy TOML for the v1 schema and the v1-to-v2 migration steps.

kortix_version: 2 requires YAML — a .toml file that declares kortix_version: 2 fails validation. A manifest that declares a version higher than 2 is rejected outright, so the platform never silently misreads a future field. Unknown top-level keys are ignored, so you can park your own metadata in the file.

validateManifest() is the single gate behind kortix ship, the change request merge check, and kortix validate. The same rules apply everywhere, so anything that merges into main is structurally sound. The schema is public and generated from the same package:

Point a kortix.yaml at the v2 schema for editor validation, or fetch it from the CLI:

# yaml-language-server: $schema=https://kortix.com/schema/kortix.v2.schema.json
kortix_version: 2
kortix schema --version 2

Full example

kortix_version: 2
default_agent: kortix

project:
  name: my-project
  description: What this project is.

env:
  required: [DATABASE_URL]
  optional: [STRIPE_API_KEY, WEBHOOK_SLACK_SECRET]

sandbox:
  templates:
    - slug: ml
      name: ML Development
      dockerfile: .kortix/Dockerfile.ml
      cpu: 4
      memory: 16

opencode:
  config_dir: .kortix/opencode

agents:
  kortix:
    connectors: all
    secrets: all
    kortix_cli: all
    skills: all

  release-bot:
    sandbox: ml
    connectors: [github]
    kortix_cli: [project.gitops.push]
    secrets: [GITHUB_AGENT_TOKEN]

triggers:
  - slug: daily-digest
    type: cron
    agent: kortix
    cron: '0 0 9 * * 1-5'
    timezone: America/Los_Angeles
    prompt: |
      Summarize yesterday's commits. Open a CR against main.

Top-level keys

Key Required Notes
kortix_version yes must be 2
default_agent yes must name a declared, enabled agent
runtime no only legal value is "opencode" (the default)
project.name / project.description no display metadata; the platform does not read project.name for the project’s display name
env.required / env.optional no env var names; required is advisory only, never enforced at session start
sandbox / sandbox.templates / sandbox.default no sandbox image(s) and hardware
opencode.config_dir no default .kortix/opencode
triggers no list of cron, webhook, and monitor triggers
connectors no list of connector definitions
policy.default_mode no allow_all (default) or risk; project-wide connector approval mode
agents yes name-to-block governance map; must not be empty

project:

Optional, human-facing metadata: name and description. The platform does not read this table for anything — a project’s display name comes from its own database record. Treat it as documentation for people reading the repo.

env:

Declares the env var names your sessions need. Values live in the dashboard’s Environment variables page, never inline in the manifest. The platform decrypts and injects them as plain env vars at session start.

env:
  required: [DATABASE_URL]
  optional: [STRIPE_API_KEY]
Field Type Notes
required string[] Advisory. The dashboard prompts the user for these, but session start does not block on a missing value.
optional string[] Available to sessions if set. Absence is fine.

Env var names match ^[A-Z_][A-Z0-9_]*$. The Secrets Manager caps a name at 64 characters — a longer name parses here but can never get a value. Names starting with KORTIX_ can never get a value either. Keep names at 64 characters or fewer, and avoid the KORTIX_ prefix. Full contract: Secrets.

sandbox: and sandbox.templates

A list of named, bootable sandbox images. Optional — with no entries, every session boots the platform’s default image. Each template needs exactly one of dockerfile (repo-relative) or image (a public Docker reference, tag- or digest-pinned).

sandbox:
  templates:
    - slug: ml
      name: ML Development
      dockerfile: .kortix/Dockerfile.ml
      cpu: 4
      memory: 16
      disk: 50
Field Type Default Notes
slug string Required. Unique per project. default is reserved.
name string slug Display label in the dashboard picker.
dockerfile string Repo-relative path. Mutually exclusive with image.
image string Public Docker image, tag- or digest-pinned. Mutually exclusive with dockerfile.
entrypoint string runtime layer’s own Overrides the container entrypoint.
cpu int provider default vCPU cores. Bound: 1–32.
memory int provider default RAM in GiB. Bound: 1–128.
disk int provider default Disk in GiB. Bound: 1–500.

Each value must be a positive integer. A value below the minimum fails validation with an error. A value above the maximum passes with a warning, then clamps at runtime. GPUs are not supported — declaring gpu produces a warning, not an error. See Runtime for what the runtime layer injects on top of your image.

sandbox.default

Set default on sandbox to make one template the project-wide default. Every session, trigger, and channel then boots it without naming a slug.

sandbox:
  default: dev
  templates:
    - slug: dev
      dockerfile: .kortix/Dockerfile

default must name a template declared in this manifest, or the reserved value "default" for the platform image.

An agent can select its environment with agents.<name>.sandbox. The value must name a manifest or dashboard template, or "default".

agents:
  researcher:
    sandbox: ml

Session template resolution uses this order:

  1. Explicit session sandbox_slug.
  2. Selected agent sandbox.
  3. Project sandbox.default.
  4. Platform "default".

Cron triggers, webhook triggers, schedules, and channels use the selected agent’s template.

A spec change (cpu, memory, disk, or the image itself) rebuilds the project’s snapshot. The new size applies on the next session, not a running one.

opencode:

Where the OpenCode config directory lives. Optional, with a default.

opencode:
  config_dir: .kortix/opencode
Field Type Default Notes
config_dir string .kortix/opencode Repo-relative directory.

That directory holds agents, skills, commands, tools, plugins, and opencode.jsonc. opencode.jsonc stays the OpenCode-native registry for plugins, MCP servers, providers, and permissions — do not duplicate those settings in the manifest. See Agents.

triggers:

A list of cron, webhook, and monitor definitions. Each entry fires a session that runs prompt as its first message.

triggers:
  - slug: daily-digest
    type: cron
    cron: '0 0 9 * * 1-5'
    prompt: Summarize yesterday's commits.
Field Required Default Notes
slug yes [a-z0-9][a-z0-9_-]{0,127}, unique among triggers.
type yes cron, webhook, or monitor (experimental).
prompt yes Non-empty. Supports templating.
name no slug Human label.
agent no default_agent Must name a key in agents:. Omit it to use default_agent; do not write the literal default.
enabled no true false skips the entry.
model no resolves at fire time Wire form provider/model. Pins the fired session to that model. See Models.
session_mode no fresh fresh, reuse, pinned, or keyed.
session_id required for pinned Exact session to re-prompt.

Cron triggers need exactly one of cron (a 6-field expression) or run_at (a one-off ISO-8601 timestamp), plus timezone as an IANA name. Webhook triggers need secret_env, the name of a secret that uses broker delivery with the connector consumer. Monitor triggers need run (a repo-relative command) and mode (poll or stream), and reject every cron and webhook field. Full field reference, credential setup, payload templating, endpoints, and session strategy: see Triggers.

connectors:

A list of external tools an agent can call. The definition lives in git; credentials live in the platform, never in the manifest. See Connectors for the conceptual model.

connectors:
  - slug: gmail-read
    name: Gmail read only
    provider: pipedream
    app: gmail
    authorization_strategy: user
    policies:
      - match: search_email
        action: always_run
Field Required Notes
slug yes [a-z0-9][a-z0-9_-]{0,127}, unique among connectors.
provider yes pipedream, mcp, openapi, postman, graphql, http, or channel.
name no Display name. Defaults to slug.
authorization_strategy no project or user. Defaults to project when omitted. A project strategy uses active project connections. A user strategy uses only the acting member’s connection.
enabled no Defaults to true.
credential no Only shared is supported. The retired per_user mode is a hard error.
sensitive no Defaults to false. true makes require_approval the unmatched-action default, including reads. Explicit project and connector rules still resolve first.

Provider-specific fields:

Provider Required field Notes
pipedream app account optional, defaults to slug.
mcp url transport: http (default) or sse.
openapi spec A URL or repo-relative path.
postman spec A Collection JSON URL or path, a .postman/api manifest, or a Postman workspace URL.
graphql endpoint spec optional (SDL).
http base_url spec optional.
channel platform slack, teams, email, or voice.
computer API-managed. You cannot declare it by hand. A profile selects one or more paired machines. See Computer Tunnel.

channel connectors rarely need a hand-written entry — connecting a channel from the dashboard creates one for you. See Slack & channels. The slugs kortix_slack, kortix_teams, kortix_email, and computer are platform-owned; using one with a different provider is a validation error. Computer Tunnel profiles are created through the connector API because tunnel ids are account control-plane identities and must not enter the manifest.

connectors.auth: optional, for providers other than pipedream. type is bearer, basic, custom, api_key, oauth1, hmac, aws_sigv4, mtls, or none (default). oauth1 is restricted to openapi, postman, and http providers. in is header (default), query, or cookie. name is required when type is custom or api_key.

connectors.policies: a list of {match, action} pairs. match is a glob over tool names. action is always_run, require_approval, or block. Policies belong to the connector. Every connection under that connector uses the same policies.

policy.default_mode: a top-level key, separate from connectors:, that sets the project-wide connector approval mode. It takes allow_all (default; every unmatched tool runs) or risk (require approval for write and destructive unmatched calls). Set it with kortix connectors policy set --default <risk|allow_all> — see CLI.

Channels

v2 removes channels: from the schema. Channel-to-agent routing (Slack, Microsoft Teams, email, and voice today) is live operational state, not declarative config. You set it from the dashboard’s Channels page or from chat commands, the same boundary that keeps credentials out of git. Connecting a channel still creates a connectors entry with provider: channel for the agent to call. See Slack & channels. The v1 [[channels]] table is covered in Legacy TOML.

agents:

A name-to-block map, keyed by agent name. This map is governance only — it grants what an agent may touch, never what it says or does.

This block is the second of the two bindings: a principal gets roles from Kortix, and an agent additionally carries the Kortix CLI scopes declared here. A session can only do what both allow. See One vocabulary, two bindings.

default_agent: kortix

agents:
  kortix:
    connectors: all
    secrets: all
    kortix_cli: all
    skills: all

  release-bot:
    connectors: [github]
    connectors_required: [github]
    kortix_cli: [project.gitops.push]
    secrets: [GITHUB_AGENT_TOKEN]
Field Default Notes
(map key) [a-z0-9][a-z0-9_-]{0,127}, unique per project. Matches the .md filename it governs.
enabled true false treats the agent as undeclared — the platform will not launch it.
connectors none Which connector slugs this agent may call. all means every connector.
connectors_required none Connector slugs that must resolve an active, strategy-compatible authorization before sandbox startup. Must be a subset of connectors. A missing authorization returns CONNECTOR_CONNECTION_REQUIRED.
secrets none Which project secrets this agent receives as sandbox env vars. Renamed from v1’s env.
kortix_cli none Which Kortix CLI and API permissions this agent may exercise. all means everything the launching user’s roles allow — an agent can never exceed its launcher.
skills none Which skills this agent may load.
workspace Git-boundary mode: runtime, read, or branch. Validated against the enum; any other value is rejected.

v2 is deny-by-default: an omitted connectors, secrets, kortix_cli, or skills on a declared agent resolves to none. Grant every permission an agent needs explicitly, as the starter’s kortix agent does above. A project migrating from v1 must re-grant everything by hand — v1 defaults env (secrets) to all when omitted, the opposite of v2.

connectors_personal remains a deprecated input alias for connectors_required. New manifests must use connectors_required. The connector’s authorization_strategy decides whether the authorization is project-owned or member-owned.

kortix_cli grants come from a fixed set of project-scoped permissions (project.read, project.gitops.push, project.gitops.merge, project.gitops.ref.any, project.trigger.*, project.secret.*, project.connector.*, and more). Account-scoped permissions — member.*, billing.*, project.create — can never be granted to an agent. Run kortix validate --scopes from inside a session to print the live, grantable list.

When config changes take effect

  • A manifest or .kortix/opencode/ edit applies only after a change request merges to main. Sessions and the trigger sweep read the default branch, not session branches.
  • A trigger’s cron or webhook change is picked up by the scheduler within seconds of the merge.
  • A sandbox image or hardware change rebuilds the snapshot. The new spec applies on the next session, not the current one.
  • A secret value change in the dashboard resolves at sandbox-create time. It applies on the next session, not a running one.

Round-trip rules

Dashboard edits are a read-modify-write on the same file. To keep diffs clean across UI and in-session edits:

  1. Keep kortix_version as the first key.
  2. Inside a trigger entry, order fields slug, name, type, agent, enabled, then type-specific fields, then prompt last.
  3. If you add a webhook trigger before its secret is set, list the secret name in env.optional. Leave the trigger enabled: false until the value is in.

Was this page helpful?