Skip to content

Agency config file ​

To set options, add an agency.json file to the directory you run Agency from.

I would suggest referring to this page as needed, instead of reading it all the way through.

Local overrides ​

Put settings you don't want to commit in agency.local.json, next to agency.json. Agency merges the two files, and the local file wins. Add agency.local.json to your .gitignore.

json
// agency.json
{ "log": { "host": "https://statelog.example.com", "projectId": "team" } }

// agency.local.json
{ "log": { "projectId": "my-project" } }

With these files, Agency logs to https://statelog.example.com under the project my-project. agency deploy reads the same settings, so it deploys to my-project.

Agency merges the files with these rules:

  1. Objects merge key by key.
  2. An array in the local file replaces the array in agency.json.
  3. Any other value in the local file replaces the value in agency.json.

The fields in this table are exceptions. A value at one of these paths replaces the matching value in agency.json whole. * stands for any name.

PathWhy
mcpServers.*A server's fields depend on each other. Mixing two servers can change how Agency connects to it.
client.modelAliases.*An alias's hash and companion models belong to its own model.

For example, if both files define an MCP server named search, Agency uses the one in agency.local.json. Servers that only agency.json defines are still used.

To see the config Agency will use, run agency config show.

If you pass -c <file>, Agency loads only that file and skips agency.local.json.

Don't put secrets in either file. Agency compiles config into the generated code, so these values can end up in build output. Keep secrets in .env.

The basics ​

json
{
  "verbose": false,
  "logLevel": "info",
  "outDir": "./dist"
}
  • verbose — extra logging during compilation.
  • logLevel — "debug", "info", "warn", or "error".
  • outDir — where compiled code goes (next to Agency source by default).

LLM client ​

This is where you set your default model, provider, and API keys.

json
{
  "client": {
    "defaultModel": "claude-fable-5",
    "defaultProvider": "anthropic",
    "apiKey": {
      "openAi": "sk-...",
      "anthropic": "sk-ant-..."
    },
  }
}
OptionDescription
defaultModel / defaultProviderUsed when a llm() call doesn't specify its own. With neither set, calls use gpt-5-mini through openai-responses. Naming a model without a provider lets the provider be inferred from the model.
apiKeyKeys for openAi, google, anthropic, ollama, openRouter, deepInfra, liteLlm, and openAiCompat.
baseUrlNeeded if you're using a provider that provides an endpoint compatible with the OpenAI API, such as openRouter, deepInfra, liteLlm and others.
maxToolResultCharsCaps how much of a single tool result the model sees (the full value still reaches your code). Default 100000; 0 disables it. Keeps a chatty tool from blowing the context window.
maxToolSchemaCharsWarns in the state log when one tool's JSON schema is longer than this. Default 2000; 0 disables it. A tool's schema is re-sent on every request, so an oversized one quietly raises the cost of the whole run.
providerModulesPaths to custom smoltalk provider modules (e.g. a local model via smoltalk-llama-cpp).
modelAliases / modelsDirShort-name aliases and the cache directory for local models.
adaptersDirThe folder LoRA adapters (.safetensors files) are in. A local image server loads one the first time a call names it: generateImageLocal(..., lora: "sketch") loads sketch.safetensors from this folder. A relative path is taken from the folder agency.json is in.
controlnetsDirThe folder ControlNets are in, one directory each. agency local download controlnet-scribble-sdxl puts one here, and generateImageLocal(..., controlnet: "controlnet-scribble-sdxl", controlImage: "./pose.png") loads it. A relative path is taken from the folder agency.json is in.
llamaCpp.draftModelA smaller GGUF model of the same family that drafts tokens for the main one, which is speculative decoding. agency run --local <model> --draft <model> sets it for a run.
llamaCpp.chatWrapperThe chat wrapper node-llama-cpp formats the model's prompts with, by its name (qwen, gemma4, harmony, chatML), for a model whose template it does not recognise.

Agency uses Smoltalk for its LLM client.

Type checking ​

The typechecker is on by default.

json
{
  "typechecker": {
    "enabled": true,
    "strict": true,
    "strictTypes": true,
    "undefinedFunctions": "warn"
  }
}
OptionDescription
enabledRun the type checker and print warnings. Defaults to true.
strictType errors become fatal. Defaults to true.
strictTypesUntyped variables are errors.
undefinedFunctions / undefinedVariables"silent", "warn", or "error" for undefined functions or variables. Both default to "warn".
strictMemberAccessGuards against accessing a member that only exists on some branches of a union. For example, if you had a Result type, and you tried to access result.value (which only exists on Success), that would be an error. Default "error".
matchExhaustivenessFlags a match over a closed type that doesn't cover every case. For example, if you were matching over a variable with a union type like "success"
definiteReturnsFlags a function that has a return type set, but not all of its code paths return a value. Default "error".

Observability and logging ​

Turns on logging. See Observability for details.

json
{
  "observability": true,
  "log": {
    "logFile": "log.jsonl"
  }
}

Memory ​

Enable the memory layer so agents can store and recall facts across runs. Setting this makes std::memory usable and lets llm({ memory: true }) inject relevant facts. See Memory for details.

json
{
  "memory": {
    "dir": "./.agency-memory",
    "autoExtract": { "interval": 5 },
    "compaction": { "trigger": "token", "threshold": 8000 }
  }
}
OptionDescription
dirWhere memory JSON files live (required if you use memory).
modelModel used for extraction, compaction, and recall.
autoExtract.intervalHow many turns to wait before running an auto-extraction on message history. Default 5.
compactionControls when a conversation gets compacted. When the thread crosses threshold, Agency extracts facts from the older messages in the conversation, summarizes them with an LLM, and replaces them with a single summary message. Roughly the older half of the conversation is compacted. Use trigger to pick the metric: either "token" (estimated at roughly 4 characters per token) or "messages" (raw message count). Defaults to trigger: "token" and threshold: 50000.
embeddings.modelEmbedding model for semantic recall.

Debugging and tracing ​

json
{
  "trace": true
}
OptionDescription
debuggerAuto-inserts a breakpoint before every step.
instrumentEmit per-step instrumentation (default true). Set false to shed the overhead when you don't need tracing.
trace / traceFile / traceDirWrite execution checkpoints to a .trace file.
distDirDirectory of pre-compiled JS the debugger imports instead of compiling on the fly.

Runtime limits ​

Safety guards that stop a program from running away.

json
{
  "maxCallDepth": 2048,
  "maxToolCallRounds": 10,
  "checkpoints": { "maxRestores": 100 }
}
OptionDescription
maxCallDepthThe runaway-recursion guard. Default 2048; raise it for legitimately deep recursion.
maxToolCallRoundsHow many times the LLM can loop between calling tools and reacting to their output before Agency halts it. Default 10.
checkpoints.maxRestoresCap on how often one checkpoint can be restored before it errors out. Default 100.

Testing and coverage ​

json
{
  "test": { "parallel": 4 },
  "coverage": {
    "threshold": 80,
    "perFileThreshold": 60,
    "exclude": ["examples/**"]
  }
}
OptionDescription
test.parallelNumber of test files to run at once. Default 1.
coverage.threshold / coverage.perFileThresholdMinimum coverage percentages; agency coverage report fails below them.
coverage.outDirWhere coverage data lands.
coverage.excludeWhich files to skip, as glob patterns (e.g. ["examples/**"]).

Eval and optimize ​

Configuration for the agency eval and agency eval optimize commands.

json
{
  "eval": {
    "runsDir": "./eval-runs",
    "optimize": {
      "goal": "Maximize accuracy",
      "graders": "./graders.ts",
      "validation": { "split": 0.2 }
    }
  }
}
OptionDescription
runsDirWhere agency eval saves its run artifacts. Default runs.
optimizeRunsDirWhere agency eval optimize saves its artifacts. Defaults to an optimize subdirectory inside runsDir.
optimize.goalThe optimization objective.
optimize.gradersPath to a TS grading module.
optimize.optimizerA built-in optimizer name or a path to your own module.
optimize.validationA validation inputs file and/or a split fraction held out for validation.

Docs, packing, and the log viewer ​

Odds and ends for other commands.

json
{
  "doc": { "outDir": "docs", "baseUrl": "https://github.com/me/repo" },
  "pack": { "format": "esm", "target": "node20" },
  "viewer": { "slowMs": 5000, "expensiveUsd": 0.01 }
}
OptionDescription
docOutput directory and source-link base URL for agency doc.
packOptions for agency pack: output format ("esm" or "cjs"), esbuild target (e.g. "node20"), and external. external is an array of package names to exclude from the bundle and import at runtime instead (for packages that can't be bundled, like native addons). Anything marked external must already be installed wherever the bundle runs.
viewerColor thresholds for agency logs view: slowMs and fastMs for durations, expensiveUsd for cost.

References ​