Syndai Docs

syndai.yaml

A file in your repo that sets policy for every run on that repo: checks, review gates, retries and more. Covers where it lives, what wins, each key and what it cannot change.

syndai.yaml is a file you commit to your repo. It sets policy for every run on that repo, so you do not have to send the same policy_config each time. You do not need it to use the API.

Where it lives

Syndai looks for the file in two places, in this order:

  1. syndai.yaml at the repo root
  2. .syndai/workflow.yaml

It reads only the first one it finds. The file can be at most 64 KB.

Syndai reads it from the repo as checked out when the run starts, before the agent changes anything. So a run that edits syndai.yaml does not change its own policy. The next run reads the new file once it is merged.

A run that fixes CI on an open pull request starts on that pull request's branch. That branch holds an earlier run's changes, so Syndai reads syndai.yaml from the pull request's base branch instead.

What wins

When the same key is set in more than one place, the one further right wins:

Syndai defaults < saved defaults < syndai.yaml < policy_config on the run

Saved defaults are the ones you set for the workspace or a project, in the app or with PUT /policy/defaults. Keys you leave out of the file keep the value from the layer below.

A few keys keep the value the run already had, whatever the file says. The run's sandbox is set up before the file is read. Anyone who can merge a change can also edit the file. So these keys are not taken from it:

  • egress.profile
  • budget.branch_strategy
  • budget.max_budget_usd
  • autonomy
  • tools.builtins and tools.disabled_builtin_capabilities, once a layer below has set them

Set these on the run, or in your saved defaults.

An example

This repo's own file is a real one. Here is a smaller example:

# syndai.yaml
version: 1

default_policy:
  validation:
    level: standard          # smoke, standard or strict
    timeout_seconds: 600     # cap for each check command, in seconds

    # Folders that hold templates you ship elsewhere.
    # Syndai never builds or tests inside them.
    template_trees:
      - tools/scaffold

    # What each check folder reads. See "validation.inputs" below.
    inputs:
      api:
        - api/
        - shared/
        - Makefile
      apps/web:
        - apps/web/
        - packages/
        - package.json
        - pnpm-lock.yaml

  reviews:
    required_gates:
      - adversarial_review

  budget:
    retry_budget: 3          # how many times a failed check may be fixed and run again

  artifacts:
    retention_profile: standard   # standard, extended or pinned

Top-level keys

keywhat it does
versionmust be 1; you can leave it out
default_policypolicy for every run on this repo, in the same shape as policy_config
validationa short form; it is merged into default_policy.validation
review_gatesa short form; each name is added to default_policy.reviews.required_gates
test_loginhow checks sign in to your app; see Test logins

Any other top-level key makes the file invalid.

default_policy

This takes the same fields as policy_config on a run. Policy lists every field. The ones people set here most:

keyvalues
validation.profileauto, python, nextjs, vite, flutter, react_native, native_ios, native_android
validation.levelsmoke, standard, strict
validation.base_freshnessas_of_base, latest_main
validation.timeout_secondsa whole number above zero
validation.template_treesa list of folders; see below
validation.inputsa map of folder to paths; see below
validation.owner_checkschecks only you can make pass; see below
reviews.required_gatesgates to add; see Review gates
budget.retry_budgeta whole number, zero or more
artifacts.retention_profilestandard, extended, pinned

To turn off the agent's web tools, set tools.disabled_builtin_capabilities: [coding.read.web_search, coding.read.web_fetch] in a saved default or on the run. That also turns off the agent's own built-in web search and fetch. It does not cut the sandbox's network: under managed_default egress a shell command can still reach the internet. To keep task text inside the sandbox, also set egress.profile: offline in a saved default or on the run. context_research_enabled is retired and does nothing: Syndai ignores it here and on a run.

Some validation keys are never accepted, here or on a run. These are commands, execution_environment, github_workflow_id, github_result_artifact_name and artifact_upload. Syndai works out the check commands itself. See Validation.

validation.template_trees

These are folders of files you ship as data, like starter kits you copy into other repos. They are not parts of this repo. Syndai never plans builds or tests inside them.

Each entry is a plain path from the repo root, like tools/scaffold. It has no slash at the start or end, and no . or .. part. You can list up to 50, with no repeats.

validation.inputs

This lists every path that a folder's checks read. Use it when a folder's checks read files outside that folder. Two common cases: a backend test suite that loads a shared schema, or a web app that builds from shared packages.

default_policy:
  validation:
    inputs:
      api: [api/, shared/, Makefile]

How it works:

  • Keys are the folders the checks run in, as Syndai's check plan names them, like api or apps/web. Use . for the repo root.
  • Values are paths from the repo root. They match whole path parts. So shared/ covers shared/x.ts, and Makefile covers only Makefile. A / at the end is optional. . means the whole repo.
  • No wildcards. The characters *, ?, [, ], \ and : are refused.
  • Each list needs 1 to 50 entries, with no repeats. You can list up to 50 folders.
  • The folder itself always counts as an input, even if you leave it out.

What it changes:

  • Skipping. A check runs only when the run's change touches one of its inputs. With no entry for a folder, its checks run when the change touches that folder. They also run when it touches a root manifest or lock file, or anything under packages/.
  • Reuse. A check may have passed earlier in the run. Later, its inputs, command and environment may all be the same. Then Syndai keeps that pass and does not run the command again. With no entry for a folder, a pass is kept only when the whole repo is unchanged.

List every path a folder's checks read. If you leave one out, it can change and the check will not run again.

validation.owner_checks

These are checks that only you can make pass. An example is a check that compares a saved result from a paid eval with the code it tested. Syndai's sandbox cannot run that eval, so the agent could never fix the check. It could only fake the saved result.

default_policy:
  validation:
    owner_checks:
      - check: check-step/check-eval-result
        step: make eval (paid), then commit evals/result.json
        paths: [evals/result.json]

Each entry has:

  • check: the check's name in Syndai's check plan, or a make target. Use a make target that make check runs as its own target, not one inside a script that runs other steps.
  • step: one line saying what you run to make it pass. Syndai shows it to you word for word.
  • paths (optional): the files your step writes, as plain paths from the repo root.

What it changes:

  • In the run. When the check fails, and nothing else fails with it, Syndai doesn't ask the agent to fix it. The run still opens its pull request. The pull request says the check needs your step.
  • In CI. A CI failure on only this check doesn't start a "Fix CI" run or offer one. It also doesn't count as passing.
  • Landing. Syndai never merges such a change itself. It waits for you when the check failed, or when the change edits one of the paths. Run the step, push the result to the pull request's branch, then merge the pull request yourself. "Merge anyway" doesn't skip this hold.

Syndai matches a check by its name. For make targets, it matches only when it re-runs your CI's make command with -k, which keeps make going after a failure. Make then prints a line for each target that failed, so Syndai can tell when only your check failed.

You can list up to 20 checks, with no repeats. Each step is one line of at most 300 characters. Each check can list up to 20 paths.

review_gates

A short way to add gates:

review_gates:
  - adversarial_review

Each name is added to reviews.required_gates. The gates planning_review, security_review and preflight are always required, with or without this list.

When the file is broken

The run fails before the agent starts if the file:

  • is not valid YAML, or its top level is not a map;
  • is larger than 64 KB;
  • has a version other than 1;
  • has a top-level key not listed above.

The run's failure reason is invalid_policy, and the message names the file and the problem.

What it cannot do

  • Turn off the three required review gates.
  • Change the network profile, branch strategy, spend cap or autonomy of a run.
  • Set check commands or a GitHub workflow to run.
  • Pick webhook events. Each endpoint picks its own with event_types; see Webhooks.

On this page