Skip to main content

.agnt.kdl Configuration

.agnt.kdl is a single file in your project root that tells agnt which scripts to run, how to link proxies to them, and what behavior to enable. It uses KDL — a node-based document format that's easier to read and write than JSON or YAML for configuration.

agnt looks for .agnt.kdl in your project directory and walks up to the filesystem root if needed. If no file exists, agnt falls back to its defaults (no scripts, no proxies).

File Structure

project {
// optional metadata
}

scripts {
// one or more named script blocks
}

proxies {
// one or more named proxy blocks
}

hooks {
on-response {
// notification behavior when AI responds
}
}

toast {
// notification display settings
}

alerts {
// process output monitoring
}

ai {
// AI agent configuration
}

project

Optional metadata block. None of these fields change behavior — they're informational.

project {
name "my-api"
type "go"
port-conflict "prompt"
}
PropertyTypeDefaultDescription
namestringDisplay name for the project
typestringProject type hint (go, node, python, dotnet-vite, etc.)
port-conflictstringpromptPolicy when a declared port is already in use. One of prompt, auto-kill, skip, fail

port-conflict policies

When agnt starts autostart scripts, it scans all declared ports for unmanaged processes already listening on them. The policy determines what happens:

PolicyBehavior
promptReturns conflicts to the client and waits for instructions
auto-killKills the blocking process tree automatically
skipLogs a warning and starts the script anyway
failAborts autostart entirely

scripts

Each named block under scripts defines a runnable process.

scripts {
dev {
run "npm run dev"
autostart true
url-matchers "Local:\\s+{url}"
ports 5173
cwd "packages/frontend"
}
}

Command properties

PropertyTypeDescription
runstringShell command to execute. Run via sh -c on Unix, cmd.exe /c on Windows
commandstringExecutable name (used with args instead of run)
argsstring[]Arguments for command
shellstringOverride the default shell (bash, powershell, cmd.exe, etc.)
shell-argsstring[]Override the default shell arguments
cwdstringWorking directory for the process. Relative to the .agnt.kdl file location
envmapEnvironment variables set for this process

Use run for shell commands. Use command + args when you need to invoke an executable directly without a shell wrapper.

// Shell command (most common)
dev { run "npm run dev" }

// Direct executable — no shell involved
server { command "node"; args "server.js" "--port" "4000" }

// Custom shell (Git Bash on Windows)
dev { run "npm run dev"; shell "C:\\Program Files\\Git\\bin\\bash.exe" }

Startup properties

PropertyTypeDefaultDescription
autostartboolfalseStart this script automatically when a session opens
depends-onstring or blockScripts that must be ready before this one starts
auto-restartboolfalseRestart the process automatically when it exits

Readiness properties

These control how agnt knows a script is ready to serve requests. Readiness matters for depends-on ordering — a dependent script won't start until its dependency signals readiness.

There are two mutually exclusive mechanisms:

url-matchers — Pattern-match the process output for a URL. When a line matches, the extracted URL is used for proxy linking and the script is marked ready. This is the preferred approach for any server that prints a startup message.

probe-port — Poll a TCP port every 500ms until it accepts a connection. Use this for servers that bind a port but don't print a recognizable URL to stdout. Requires ports to be set. Mutually exclusive with url-matchers.

If neither is set, the script is marked ready when it starts or exits — no readiness gating occurs.

PropertyTypeDescription
url-matchersstring[]Regex patterns to match against process output. Use {url} as a placeholder for localhost URLs
probe-portboolEnable TCP port polling for readiness. Requires ports
// Preferred: match the server's startup message
backend {
run "dotnet watch run --project src/App.csproj"
url-matchers "Now listening on {url}"
ports 5000
}

// Fallback: server binds port silently, no startup message
worker {
run "./background-worker"
ports 8080
probe-port true
}

Port properties

PropertyTypeDescription
portsint[]Ports used by this process. Used for pre-flight conflict detection and EADDRINUSE recovery

ports serves two purposes regardless of the readiness mechanism:

  • Pre-flight: Before starting, agnt checks if something else is already listening on these ports
  • EADDRINUSE recovery: If the process fails to start because a port is in use, agnt can retry after clearing it

Health monitoring properties

PropertyTypeDescription
error-patternstringRegex that flags the process as unhealthy when matched in output
healthy-patternstringRegex that clears the unhealthy flag when matched in output

If neither is set, agnt uses built-in patterns that cover common frameworks (Go, Node, Python, .NET).

depends-on

Controls startup order between scripts. A script with depends-on waits for all listed dependencies to reach a ready state before starting.

scripts {
backend {
run "go run ./cmd/server"
url-matchers "Listening on {url}"
autostart true
}
frontend {
run "npm run dev"
autostart true
depends-on "backend"
url-matchers "Local:\\s+{url}"
}
}

The dependency is satisfied when the backend script either prints a URL matching its url-matchers or reaches a port probe success. If the backend crashes or exits before becoming ready, the frontend starts anyway with a warning.

Per-dependency timeout — default is 120 seconds, configurable per dependency:

// All dependencies get the same timeout
frontend {
depends-on "backend" "redis" timeout=60
}

// Per-dependency timeout
frontend {
depends-on {
api timeout=30
worker timeout=120
}
}

proxies

Each named block under proxies defines a reverse proxy into a dev server.

proxies {
app {
script "dev"
fallback-port 5173
}
}

Proxy properties

PropertyTypeDefaultDescription
autostartboolfalseStart automatically when the session opens
scriptstringLink to a script — proxy target is auto-detected from script's URL output
url-patternstringRegex filter for which detected URLs to use. Filters on the full URL string
fallback-portintPort to use if URL detection from the script fails
urlstringDirect target URL (e.g., http://localhost:3000)
portintDirect target port (shorthand for http://localhost:PORT)
targetstringDeprecated. Use url instead
hoststringlocalhostTarget hostname
bindstring127.0.0.1Listen address. 0.0.0.0 to expose on all interfaces (for tunnel/mobile testing)
websocketboolfalseEnable WebSocket proxying
max-log-sizeint1000Maximum traffic log entries to keep

Script-linked proxies

When a proxy has script set, agnt creates it automatically when the linked script prints a URL matching its url-matchers. This is the most common setup — no hardcoded ports.

scripts {
dev {
run "npm run dev"
url-matchers "Local:\\s+{url}"
autostart true
}
}

proxies {
app {
script "dev"
fallback-port 5173
}
}

fallback-port is a safety net. If the dev server starts but its URL output doesn't match the pattern (or the process doesn't print a URL at all), agnt creates the proxy targeting localhost:fallback-port after a delay.

Explicit target proxies

When a proxy has a direct url or port set and no script, it starts on its own:

proxies {
external-api {
url "http://localhost:8080"
autostart true
}
}

URL pattern filtering

Some servers print multiple URLs (e.g., Wails prints both a Vite frontend URL and a backend URL). url-pattern filters which one the proxy targets:

proxies {
// Only proxy the Wails backend, not the Vite frontend
wails-app {
script "wails-dev"
url-pattern ":34115"
}
}

hooks

Controls what happens when the AI agent responds.

hooks {
on-response {
toast true
indicator true
sound false
}
}
PropertyTypeDefaultDescription
toastbooltrueShow a toast notification in the browser
indicatorbooltrueUpdate the floating indicator
soundboolfalsePlay a notification sound

toast

Controls toast notification display.

toast {
duration 4000
position "bottom-right"
max-visible 3
}
PropertyTypeDefaultDescription
durationint4000Display duration in milliseconds
positionstringbottom-rightOne of top-left, top-right, bottom-left, bottom-right
max-visibleint3Maximum simultaneous toasts

alerts

Controls process output monitoring. agnt scans process stdout/stderr for error patterns and surfaces them through get_errors.

alerts {
enabled true
batch-window 3
dedupe-window 60

patterns {
"db-connection" {
pattern "ECONNREFUSED"
severity "error"
}
}

disable "connection-refused"
}
PropertyTypeDefaultDescription
enabledbooltrueEnable or disable alert monitoring entirely
batch-windowint3Seconds to collect alerts before delivering (reduces noise)
dedupe-windowint60Seconds to suppress duplicate alerts
patternsmapCustom alert patterns keyed by ID
disablestring[]Built-in pattern IDs to disable

Each custom pattern has:

PropertyTypeDescription
patternstringRegex matched against each output line
severitystringerror, warning, or info

ai

Controls how agnt configures AI agent sessions started with agnt run or agnt ai.

ai {
skill "code-review"
env {
ANTHROPIC_API_KEY "sk-..."
}
append-system-prompt "This project uses GraphQL. Always check the schema before writing queries."
}
PropertyTypeDescription
skillstringSkill/persona name to apply to the session
envmapEnvironment variables set for AI commands
system-promptstringFull system prompt replacement
append-system-promptstringText appended to the default agnt system prompt

Use append-system-prompt over system-prompt — the default prompt includes tool documentation for agnt's MCP tools, which system-prompt would discard entirely.

Complete Examples

Single Vite app

scripts {
dev {
run "npm run dev"
autostart true
url-matchers "(Local|Network):\\s*{url}"
}
}

proxies {
app {
script "dev"
}
}

hooks {
on-response {
toast true
indicator true
}
}

Full-stack with separate backend and frontend

scripts {
backend {
run "go run ./cmd/server"
autostart true
url-matchers "Listening on {url}"
ports 4000
}
frontend {
run "npm run dev"
cwd "web"
autostart true
depends-on "backend"
url-matchers "Local:\\s+{url}"
ports 5173
}
}

proxies {
app {
script "frontend"
fallback-port 5173
}
}

hooks {
on-response {
toast true
indicator true
}
}

.NET backend with silent worker process

scripts {
api {
run "dotnet watch run --project src/Api.csproj"
autostart true
url-matchers "Now listening on {url}"
ports 5000
}
worker {
run "./worker --port 8080"
autostart true
ports 8080
probe-port true
}
}

proxies {
app {
script "api"
fallback-port 5000
}
}