Skip to content
Kortix
Esc
↑↓navigate↵open⌘Jpreview
On this page

kortix.yaml reference

Every kortix.yaml key with its type, default and validation rule, how to validate the file, and how to migrate from kortix.toml.

kortix.yaml is the manifest at the root of a project repository. It declares the agents and what each one may reach, plus the triggers, connectors, secret names, sandbox templates, harness settings and Apps of the project. This page is the key-by-key reference for people who write or review the file by hand. For the repository layout, see Projects.

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

env:
  optional: [STRIPE_API_KEY]

agents:
  kortix:
    file: agents/kortix.md
    connectors: all
    secrets: all
    skills: all
    kortix_permissions: all

File and schema

The project’s manifest_path (default kortix.yaml) sets where Kortix looks. Change it with kortix projects set --manifest <path> or in Customize → Settings. Kortix reads the first file that exists of kortix.yaml, kortix.yml and kortix.toml at that path. A repository with both a YAML and a TOML file uses the YAML file.

Add the schema line at the top of the file. A YAML editor then validates and completes every key:

# yaml-language-server: $schema=https://kortix.com/schema/kortix.v2.schema.json
Schema URL
v1 https://kortix.com/schema/kortix.v1.schema.json
v2 https://kortix.com/schema/kortix.v2.schema.json
v3 https://kortix.com/schema/kortix.v3.schema.json
All versions (selects by kortix_version) https://kortix.com/schema/kortix.schema.json

kortix schema prints the combined schema. kortix schema --version 2 prints one version, and --url prints its URL instead of the body.

Validate before you push:

kortix validate                       # ./kortix.yaml
kortix validate --file config/kortix.yaml --json
kortix validate --scopes              # print every grantable kortix_permissions entry
Flag Effect
--file <path> Validate this file instead of the project manifest in the current directory.
--json Print a JSON report: valid, path, issues.
--scopes Print the grantable kortix_permissions entries and their aliases, then exit.
--no-dockerfile-lint Skip the checks on sandbox template Dockerfiles.

kortix validate exits 0 with no errors, 1 with one or more errors, and 2 when the file is missing or unreadable. The same schema check runs in kortix ship and in the change request merge check. An error blocks the push or the merge. A warning never does. Kortix ignores unknown top-level keys.

The CLI also checks the files around the manifest. In a v2 manifest it reports these as errors:

  • a missing agent .md;
  • a missing tool module;
  • a skill with no skills/<name>/SKILL.md;
  • an agent connectors or connectors_required slug that connectors does not declare (kortix_slack, kortix_teams, kortix_email and computer always count as declared);
  • an agent secrets or trigger secret_env name that env does not declare.

It lints each template Dockerfile. It warns when the files in Git exceed 512 MiB or when one file reaches 10 MiB.

Versions

kortix_version is required and picks the schema.

Version Format Agent behavior Notes
1 kortix.toml or YAML In the agent .md Legacy. Reads and runs. See Migrate from kortix.toml.
2 YAML only In agents/<name>.md (prompt and frontmatter) kortix init and Create project write v2. The dashboard agent editor writes v2. An omitted grant means none.
3 YAML only Inline in kortix.yaml: prompt or prompt_file, model, mode, permission, description Rejects agents.<name>.file, agents.<name>.disable and the top-level opencode key. Write and edit it by hand. The dashboard agent editor edits only v2 manifests and shows a v3 agent read-only.

A version above 3 is an error. A kortix.toml that declares version 2 or 3 is an error. No automatic migration from v2 to v3 exists.

A v3 agent carries its behavior in the manifest:

kortix_version: 3
default_agent: support
agents:
  support:
    description: Answers questions from the help desk.
    mode: primary
    prompt_file: prompts/support.md     # or prompt: "You answer…", not both
    permission:
      bash: ask
    secrets: [HELPDESK_TOKEN]

A v3 agent block also takes variant, temperature, top_p, steps, color, hidden and options. prompt_file is a repository-relative .md path. A v3 agent gets no project repository in /workspace unless it sets workspace: { project_repository: true }. See Workspace.

Top-level keys

Key Type Default Rule
kortix_version integer required 1, 2 or 3.
default_agent string required (v2, v3) Names a declared agent that is not enabled: false. Sessions and triggers that name no agent use it.
agents map required (v2, v3) Agent name to agent block. At least one agent. See agents.
imports list none Other YAML files whose collections merge into this one. See imports.
project map none name, description. For people who read the repository. The project name in Kortix does not come from here.
env map none required, optional: secret names. See env.
runtime string opencode opencode or pi. See harnesses, opencode and pi.
harnesses map none pi.packages, opencode.plugins.
opencode.config_dir path harnesses/opencode, then .kortix/opencode OpenCode config directory. An error in v3.
pi.config_dir path harnesses/pi, then .kortix/pi pi config directory.
tools map all five Kortix tools Tool name to kortix:<name> or a module path. See Tools.
commands map none v3 only. Slash command name to its template. See commands (v3).
sandbox map platform image templates, default. See sandbox.
triggers list none Schedules, webhooks, monitors, app events.
connectors list none Apps, APIs and MCP servers an agent can call.
apps map none App slug to App configuration.
policy.default_mode string allow_all allow_all or risk. See policy and policies.
policies list none Project-wide connector rules.
approvals.ttl string 24h How long a held connector call waits for a decision. See policy and policies.

A v2 or v3 manifest rejects channels, sandboxes, and the image keys image, dockerfile, slug, cpu, memory, disk, entrypoint, context, context_dir and gpu set directly on sandbox.

imports

imports splits one manifest across several YAML files. The platform resolves every import and works on the merged document: validation, triggers, agent grants and connector sync all see one manifest.

# kortix.yaml
kortix_version: 2
default_agent: kortix
imports:
  - triggers/          # every .yaml and .yml file below this directory
  - agents.yaml        # one file
agents:
  kortix:
    connectors: all
# triggers/reports/weekly.yaml
triggers:
  - slug: weekly-report
    type: cron
    agent: kortix
    cron: "0 0 15 * * 0"
    prompt: Build the weekly report.
  1. A path is relative to the repository root. .., absolute paths and globs are errors. A path that matches no .yaml or .yml file is an error.
  2. A directory import takes every .yaml and .yml file below it, at any depth, sorted by path.
  3. An imported file declares triggers, connectors, agents, apps, tools and imports. kortix_version, default_agent, runtime, project, env, opencode, sandbox, policy and policies in an imported file are errors. Kortix drops any other key in an imported file, for example harnesses.
  4. Imports nest up to 8 levels and 200 files. A cycle is an error. A file reached twice merges once.
  5. One name, one file. A trigger slug, connector slug, agent name, App slug or tool name declared in two files is an error that names both files.
  6. Entries merge in order: the importing file first, then its imports as listed.

A broken import fails the whole manifest:

imports: triggers "weekly-report" is declared in both triggers/a.yaml and triggers/b.yaml — one name, one file

agents

agents maps an agent name to its governance block: whether it may run and what it may reach. In v2 the behavior (prompt, model, mode, permissions) lives in the agent .md. What each grant means is on Agents & permissions.

An agent name matches [a-z0-9][a-z0-9_-]{0,127}.

Field Default Rule
file agents/<name>.md v2 only. The agent .md, relative to the repository root.
enabled true Boolean. false: Kortix does not start the agent.
connectors none Grant set of connector slugs.
secrets none Grant set of secret names the agent receives in its sandbox.
skills the .md decides Grant set of skill names. Set, it overrides permission.skill in the agent .md. Omitted, the .md rule applies.
apps none Grant set of App slugs the agent may open when the App access is restricted or private.
commands none v3 only. Grant set of command names from the top-level commands. The agent runs only these.
kortix_permissions none Grant set of project permissions. Capped by the agent’s ceiling role, never by the role of the person who starts the session. See What an agent may do.
tools all all, none, a list of tool names, or { exclude: [names] }. The map form { bash: false } also works.
sandbox project default A sandbox template slug, or default.
workspace.project_repository v2 true, v3 false Boolean. true: new sessions of this agent check out the project repository. false: no project repository in /workspace and no repository access. See Workspace.
harnesses none Per-agent pi.packages, pi.exclude, opencode.plugins, opencode.exclude.
network_egress none Declaration only. Accepts { version: 1, default: deny, rules: [] } and warns that egress is not enforced.

A grant set is all (or *), none (or ""), or a list of names. A list that contains * means all.

file rules. The path ends in .md. It does not start with / or -. It has no ., .. or empty segment. Each segment uses letters, digits, _, -, . and spaces. With file omitted, Kortix reads agents/<name>.md, then .kortix/opencode/agents/<name>.md, or <opencode.config_dir>/agents/<name>.md when that key is set. The API refuses a request that changes file (400, invalid_config). To move an agent, move its .md and edit file in the same commit.

kortix_permissions rules. Each entry is a project permission. kortix validate --scopes prints the list. Account permissions such as member.*, billing.* and project.create are errors. The alias entries project.cr.open, project.cr.merge, project.customize.read and project.customize.write resolve to their current permissions and warn. The no-op entries project.session.exec, project.gateway.routing.edit, project.schedule.*, project.webhook.* and channel.* are errors in v2 and v3.

Errors in a v2 agent block. env (use secrets), and every behavior key: description, model, mode, variant, temperature, top_p, options, color, steps, hidden, prompt, prompt_file, permission, disable, opencode. The message points at the agent .md.

Deprecated fields.

  • connectors_required: parsed, must be a subset of connectors, not read at session start.
  • connectors_personal: alias of connectors_required. Warns.
  • kortix_cli: alias of kortix_permissions. Warns. A different value from kortix_permissions is an error.
  • repository_access: alias of workspace.project_repository. A different value is an error.
  • workspace as a string: branch means project_repository: true, and runtime means false. read without an explicit boolean refuses session start (409, WORKSPACE_MODE_UNAVAILABLE).

Agent workspace

workspace sets what new sessions of the agent get in /workspace. It has one key today:

agents:
  engineer:
    workspace:
      project_repository: true   # v3 default false, v2 default true
  • project_repository: true: the session checks out the project repository on its own session branch. Set it on every agent that reads or edits the repository, runs scripts from it, or opens change requests.
  • project_repository: false: the session gets no checkout, no git variables, and no repository API access (403). Its project tools still load: the sandbox receives only the modules of the tools the agent may call.
  • Omitted: false in kortix_version: 3, true in versions 1 and 2. A v2 project keeps its behavior. The starter, kortix init, Create project, the agent editor and kortix migrate write the value explicitly, so a new or migrated agent states it.
  • A running session keeps the value it started with. A change applies to new sessions.
  • Any other key under workspace is an error. A typo does not fall back to the default: Kortix withholds the repository from that agent until the block is fixed.

commands (v3)

In v3, a slash command is declared in kortix.yaml. The project registers it under commands, and each agent that may run it enables it by name. v3 reads no harness folder, so harnesses/opencode/commands/ and harnesses/pi/prompts/ are not read.

kortix_version: 3
default_agent: support
commands:
  triage:
    description: Sort a ticket by urgency.
    prompt: "Read ticket $1 and reply with its urgency: low, normal or high."
  release-notes:
    prompt_file: prompts/release-notes.md
agents:
  support:
    prompt_file: prompts/support.md
    commands: [triage, release-notes]   # or: all
Key Rule
name Lowercase letters and digits, in words joined by -. At most 64 characters.
prompt The template, as a non-empty string.
prompt_file A repository path to a .md file. Kortix uses the whole file as the template; it does not remove a frontmatter block.
description Optional. Shown in the / menu.
  • Set exactly one of prompt or prompt_file. Any other key is an error. An agent key points you to agents.<name>.commands.
  • $ARGUMENTS takes everything typed after the command. $1, $2 and so on take the words in order, and the highest one takes the rest. A template with neither gets the arguments appended.
  • An agent runs only the commands its commands grant names: all, none or a list. Omitted means none. A command that no agent enables is left out.
  • Running a command on an agent that does not enable it answers 403 with {"error": "command_not_enabled", "command": "<name>", "agent": "<agent>"}.
  • Commands come from the manifest on the project’s default branch.

env

env declares the secret names the project expects. Values live in Secrets, never in the manifest.

env:
  required: [DATABASE_URL]
  optional: [STRIPE_API_KEY]
Field Type Effect
required list of names The dashboard and kortix ship prompt for a missing value. A missing value never blocks a session.
optional list of names Offered by the same prompts.

A name matches ^[A-Z_][A-Z0-9_]*$. Any other key under env warns. kortix ship --no-env skips the prompts. In a v2 manifest, kortix validate requires every name in an agent secrets list and every trigger secret_env to appear here.

The Secrets store refuses a name longer than 64 characters or one that starts with KORTIX_. Such a name validates here but never gets a value. Only the Teams connection sets MS_TEAMS_* names, and only ChatGPT subscription onboarding sets CODEX_AUTH_JSON.

sandbox

sandbox.templates lists named sandbox images. With no template, every session boots the platform image. What Kortix adds on top of an image is on Sandboxes & previews.

sandbox:
  default: ml
  templates:
    - slug: ml
      name: ML development
      dockerfile: Dockerfile.ml
      cpu: 4
      memory: 16
      disk: 50
Field Default Rule
slug required Unique. default is reserved. A slug over 64 characters warns: the runtime drops it.
name slug Label in the template picker.
dockerfile — Repository-relative path. Set exactly one of dockerfile and image.
image — Public image with a tag or a digest. No tag is an error. :latest warns.
entrypoint the image’s Overrides the container entrypoint.
cpu provider default vCPU cores, 1–32.
memory provider default GiB, 1–128.
disk provider default GiB, 1–500.
container_runtime false true runs Docker in the sandbox. See Hardware and Docker.

A hardware value is a positive integer. A value below the minimum is an error. A value above the maximum warns and is clamped. gpu warns and does nothing.

sandbox.default names a template in this manifest, or default for the platform image. A session picks its template in this order:

  1. The sandbox_slug of the session request.
  2. The sandbox of the agent the session starts with.
  3. sandbox.default.
  4. The platform image.

A template change applies to the next session, not to a running one.

harnesses, opencode and pi

A session runs one of two harnesses. The project’s pi_harness feature flag (on by default) or runtime: pi selects pi. runtime decides only while the flag is off. See Harnesses: OpenCode and pi.

Key Default Holds
opencode.config_dir harnesses/opencode, then .kortix/opencode Files only OpenCode reads: opencode.jsonc, plugins/, tools/. Without the key, Kortix uses the first directory that holds an opencode.json or opencode.jsonc.
pi.config_dir harnesses/pi, then .kortix/pi Files only pi reads: settings.json, extensions/, skills/, prompts/.

harnesses.pi.packages lists the pi packages every pi session loads:

runtime: pi
harnesses:
  pi:
    packages:
      - npm:pi-web-access@0.30.0          # exact version
      - source: npm:pi-mcp-adapter@2.36.0
        extensions: ["extensions/*.ts"]   # load only these files
        skills: []                        # load none of its skills
      - ./extensions/audit.ts             # one extension file in this repository
agents:
  reviewer:
    harnesses:
      pi:
        exclude: [pi-web-access]          # package name, no version
        packages: [npm:@my-org/pi-review@1.2.0]   # this agent only
  • An entry is npm:<name>@<x.y.z> (an exact version), a ./ path that stays inside the repository, or { source, extensions, skills, prompts, themes }. An omitted filter loads everything. [] loads nothing.
  • A ./ path to a .ts or .js file is one extension. It can live anywhere in the repository, so a project needs no harnesses/pi/ folder. It loads from the session’s config release, and a change to a file in its folder restarts the pi runtime.
  • A session reads the package list when it starts. A running session keeps its list until it restarts.
  • At most 20 entries. A range, a missing version and a git source are errors.
  • An agent loads the top-level list, minus its exclude, plus its own packages. exclude exists only on an agent.
  • The change request merge builds the packages. A session never runs npm install. A session that starts before the build exists boots without the project packages.

harnesses.pi.codemode sets pi’s codemode tool. The model writes one JavaScript script that calls the other tools (await tools.bash({ command })), and only the script’s output reaches the model, so one call can batch, chain and filter several tool calls.

harnesses:
  pi:
    codemode: on        # on (default) | only | off
agents:
  reviewer:
    harnesses:
      pi:
        codemode: off   # this agent only
Value The model gets
on (default) every tool, plus codemode
only codemode alone; every other tool runs from a script
off no codemode
  • An agent’s value replaces the top-level one. Read when the session starts.
  • A script’s calls pass the same permission policy as direct calls: a deny rule blocks them, and an ask rule pauses the script until someone answers.
  • A script cannot start a subagent (task) or ask a question (question). The model calls those directly.
  • Scripts run in a sandboxed JavaScript VM (QuickJS) with no file system, network or timers. They reach the box only through the tools.

harnesses.opencode.plugins (v2) lists the files in <opencode config dir>/plugins/ that load, for example audit.ts. Without the key, every plugin file loads. An agent adds its own with agents.<name>.harnesses.opencode.plugins and drops top-level ones with exclude. A listed file that does not exist fails the config build.

tools

tools maps a tool name to kortix:<name> (a Kortix tool) or a repository-relative .ts or .js module. With no tools key, sessions get all five Kortix tools. With a tools key, sessions get only the tools it lists. The rules, errors and module contract are on Tools.

triggers, connectors, apps

A trigger or connector entry is identified by its slug, and an App by its key under apps. Each one matches [a-z0-9][a-z0-9_-]{0,127} and is unique in its collection.

triggers. Full reference: Triggers & reminders.

Field Rule
slug, type, prompt Required. type is cron, webhook, monitor or event. prompt is a non-empty template.
name, agent, enabled, model Optional. agent defaults to default_agent and names a declared agent. model is provider/model.
session_mode fresh (default; reuse for a monitor), reuse, pinned (needs session_id) or keyed (needs session_key).
filter Optional. Map of dotted path to expected string. A fire runs only when every path matches. See Triggers & reminders.
cron type cron (6 fields, seconds first) or run_at (ISO-8601), and timezone (IANA, default UTC). Fires at most once every 60 seconds.
webhook type secret_env: the name of the signing secret.
monitor type run (one command line, at most 1,024 characters) and mode (poll or stream). poll needs interval, at least 30s. Optional expect_event_within, at least 5m. Needs the monitors feature flag, off by default.
event type connector and event. Optional account, source, config. Needs the event_triggers feature flag, off by default.

A monitor trigger rejects cron, run_at, timezone and secret_env. An event trigger rejects every cron, webhook and monitor field. connector, event, account, source and config are errors on any type except event.

connectors. Full reference: Connectors. Credentials live in the platform, never in the manifest.

Field Rule
slug, provider Required. provider is composio, pipedream, mcp, openapi, postman, graphql, http or channel.
Provider field composio and pipedream: app. mcp: url, optional transport (http or sse). openapi and postman: spec. graphql: endpoint. http: base_url. channel: platform (slack, teams or email).
name, enabled Optional.
authorization_strategy project (default) or user.
credential shared only.
sensitive true: an unmatched call needs approval.
auth type: bearer, basic, custom, api_key, oauth1, hmac, aws_sigv4, mtls or none. in: header (default), query or cookie. name for custom and api_key. oauth1 only on openapi, postman and http.
headers Static headers, at most 32. Never a credential.
policies List of { match, action }. match is a glob over tool names. action is always_run, require_approval or block.

computer is not a valid provider: connecting a computer creates that connector. The slugs kortix_slack, kortix_teams, kortix_email and computer are reserved for the built-in connectors. Connecting a channel writes its channel connector for you: see Slack, Teams & email.

apps. Full reference: Configure in kortix.yaml.

apps maps an App slug to its configuration. The keys are path, type (static, bundle, dockerfile, oci_image), image, dockerfile, command, port, root, output_dir, install_command, build_command, spa, readiness_path, idle_timeout_seconds, always_on, uses, resources, env, secrets, processes, http_service, services, mounts, vm, deploy and labels. Any other key is an error.

policy and policies

policy.default_mode decides a connector call that no rule matches:

  • allow_all (default): the call runs.
  • risk: a read runs; a write or destructive call needs approval.

policies holds project-wide rules. A rule matches a fully qualified tool path, <connector-slug>.<tool>, with * globs. Kortix checks project rules first, then the connector’s own policies. The first matching rule wins. conditions limits a rule to calls whose arguments match:

policy:
  default_mode: risk
policies:
  - match: gmail.send_email
    action: require_approval
    conditions:
      - arg: to
        match: "*@example.com"     # a glob, or /regex/ in slashes
  - match: gmail.send_email
    action: block

approvals.ttl sets how long a held call waits for a decision: an integer and m, h or d, such as 30m, 4h or 7d. Kortix clamps it to 5 minutes through 30 days. Without it, or with any other value, a held call waits 24 hours. A held call that nobody decides in time expires.

approvals:
  ttl: 4h

All conditions of a rule must hold. negate: true inverts one condition. How approvals reach a person is on Policies and approvals.

kortix validate does not check policy or policies. When Kortix syncs connectors, it skips a malformed rule and reports it as a connector sync error. Check the rules in the connector settings after the merge.

Dashboard and CLI edits

The dashboard and the API edit the manifest in the project repository. kortix triggers add|rm|enable|disable edit the local file, and kortix ship pushes it. With --apply, they change the project now. In each case:

  • An edit to an entry rewrites only the file that declares it, the root or an imported file. A new entry goes to the root file.
  • Keep kortix_version as the first key.
  • Write trigger fields in the order the editor writes them: slug, name, type, agent, model, enabled, the session fields, filter, the type fields, then prompt.

A manifest edit takes effect when it reaches the default branch. A dashboard, API, SDK or --apply edit commits there at once. Any other edit takes effect when kortix ship, a direct push or a change request merge brings it there. See How a change takes effect.

Migrate from kortix.toml

Kortix reads and runs a v1 kortix.toml. To move it to v2, open Customize → Settings → Upgrades and run Migrate manifest to v2 (kortix.yaml), or run:

kortix projects upgrade [<id>]

Both start a session with the project’s default agent. The agent rewrites the manifest, runs kortix validate and opens a change request. The session never merges it. Starting it needs permission to start sessions in the project.

To migrate by hand:

  1. Turn the [[agents]] array into the agents: map, keyed by name, and add default_agent.
  2. Rename each agent env to secrets. v1 gives an agent every secret when env is omitted. v2 gives none, so list every secret and connector each agent needs.
  3. Delete [[channels]] and reconnect each channel from the dashboard.
  4. Write each [[sandbox.templates]], [[triggers]] and [[connectors]] table as a YAML list entry with the same fields.
  5. Remove credential = "per_user", agent_scope, and the no-op kortix_permissions entries. All three are errors in v2.
  6. Run kortix validate --file kortix.yaml, then delete kortix.toml.

Was this page helpful?