# Configuration Reference ## Config Discovery And Precedence Application settings are resolved in this order: 1. built-in defaults 2. `config.yml` values 3. CLI overrides When `--config` is omitted, Scriptorium searches: 1. `/usr/local/etc/scriptorium/config.yml` 2. `/etc/scriptorium/config.yml` If neither file exists, Scriptorium uses built-in defaults. When `--config ` is provided, that file must exist and decode successfully. ## Minimal Working Config ```yaml prompt_dir: ./examples/prompts ``` This is enough for `run` and `render` when selected prompts use built-in profiles. Set `profile_dir` when prompts or requests use custom profiles. The maintained repository example is `examples/config.yml`. ## Production-Oriented Config ```yaml prompt_dir: /opt/scriptorium/prompts profile_dir: /opt/scriptorium/profiles schema_dir: /opt/scriptorium/schemas server: addr: 127.0.0.1:8080 artifact_root: /var/lib/scriptorium/artifacts max_request_bytes: 16777216 max_artifact_bytes: 16777216 max_response_bytes: 16777216 defaults: render_format: text ``` The maintained full example is `examples/config.full.yml`. ## App Config Reference Top-level fields: | Field | Default | Description | | --- | --- | --- | | `prompt_dir` | unset | Directory containing prompt definition YAML files. Required effectively by `run`, `render`, and `serve`. | | `profile_dir` | unset | Directory containing custom profile YAML files. Built-in profiles remain available when unset. | | `schema_dir` | `.` | Base directory for relative JSON Schema paths. | | `server` | `{}` | HTTP service settings used by `serve`. | | `defaults` | `{}` | Adapter defaults. | `server` fields: | Field | Default | Description | | --- | --- | --- | | `server.addr` | `:8080` | Listen address for `serve`. | | `server.artifact_root` | unset | Base directory for HTTP `file` input references. Without it, HTTP file refs are rejected. | | `server.max_request_bytes` | `16777216` | Maximum encoded HTTP request body bytes. `0` disables the limit. | | `server.max_artifact_bytes` | `16777216` | Maximum HTTP file artifact bytes. `0` disables the limit. | | `server.max_response_bytes` | `16777216` | Maximum encoded HTTP response bytes. `0` disables the limit. | `defaults` fields: | Field | Default | Description | | --- | --- | --- | | `defaults.render_format` | `text` | Default `render` output format: `text` or `json`. | Config rules: - YAML decoding is strict; unknown fields are rejected. - HTTP size limits must be greater than or equal to `0`. - Empty string config values are ignored. - Raw API key fields are not supported in app config. ## Prompt Definition Files Prompt definitions are YAML files anywhere under `prompt_dir`. Nested directories are organizational; callers select prompts by YAML `id`, not file path. Example: ```yaml id: generic.structured_events version: "1.0.0" default_profile: local-quality description: Produce structured event JSON from a transcript. inputs: - name: transcript required: true content_type: text/markdown description: Source transcript content - name: glossary required: false content_type: text/yaml description: Optional glossary context messages: - role: system content_file: ./generic.structured_events.system.md - role: user content_file: ./generic.structured_events.user.md output: format: json validation_mode: json_schema schema_path: structured_events.schema.json repair_attempts: 0 ``` Prompt fields: | Field | Required | Description | | --- | --- | --- | | `id` | yes | Prompt identifier used by `--prompt` and HTTP `prompt_id`. | | `version` | yes | Prompt version. | | `default_profile` | no | Profile ID used when a request does not provide a profile. | | `description` | no | Human-readable description. | | `session_id` | no | Go-template string rendered from request vars and forwarded as provider `session_id` when non-empty. | | `inputs` | no | Named input declarations. | | `messages` | yes | Chat message templates. | | `output` | yes | Output format and validation contract. | `inputs[]` fields: - `name` (required) - `required` (optional boolean) - `content_type` (optional metadata) - `description` (optional) `messages[]` fields: - `role` (required) - exactly one of `content` or `content_file` - `cache_control` (optional) Message rules: - `content_file` resolves relative to the prompt YAML file location. - Repeated roles are allowed. - Prompt YAML decoding is strict. - Duplicate input names are invalid. - Duplicate prompt IDs are invalid for a requested ID/version. `messages[].cache_control` fields: | Field | Required | Supported values | | --- | --- | --- | | `type` | yes | `ephemeral` | | `ttl` | no | `1h` | `session_id` behavior: - Rendered with the same variable context as message templates. - Trimmed and omitted when empty. - Rejected when longer than 256 Unicode code points. - CLI callers pass variables with `--var`; HTTP callers use `vars`. `output` fields: | Field | Required | Supported values | | --- | --- | --- | | `format` | yes | `text`, `markdown`, `json` | | `validation_mode` | yes | `none`, `basic`, `json`, `json_schema` | | `schema_path` | only for `json_schema` | Relative to `schema_dir` unless absolute. | | `repair_attempts` | yes | Integer greater than or equal to `0`. | Repair boundary: - `repair_attempts` is part of the prompt contract. - The current CLI and HTTP wiring constructs the runner without a repairer, so normal `run` and `serve` execution does not perform repair attempts. ## Profile Definition Files Execution profiles are YAML files anywhere under `profile_dir`. Nested directories are organizational; callers select profiles by YAML `id`, not file path. Scriptorium also ships built-in profiles. Custom profiles override built-ins with the same ID. Example: ```yaml id: local-fast endpoint: http://localhost:8000/v1 model: gpt-4o-mini temperature: 0.2 max_tokens: 500 top_p: 1.0 timeout_seconds: 90 api_key_env: SCRIPTORIUM_API_KEY service_tier: priority reasoning_effort: medium extra_params: provider_route: primary ``` Profile fields: | Field | Required | Description | | --- | --- | --- | | `id` | yes | Profile identifier. | | `endpoint` | yes | OpenAI-compatible base URL including `/v1`. | | `model` | yes | Provider model name. | | `temperature` | no | Range `0..2`. | | `max_tokens` | no | Integer greater than or equal to `0`. | | `top_p` | no | Range `0..1`. | | `timeout_seconds` | no | Integer greater than or equal to `0`. | | `service_tier` | no | Provider-specific request tier. | | `reasoning_effort` | no | Provider-specific reasoning setting. | | `api_key_env` | no | Environment variable name containing the API key. | | `extra_params` | no | JSON-compatible provider-specific top-level request fields. | Execution defaults before profile/request overrides: | Field | Default | | --- | --- | | `temperature` | `0.0` | | `max_tokens` | `0` | | `top_p` | `1.0` | | `timeout_seconds` | `600` | Profile rules: - Profile YAML decoding is strict. - Duplicate custom profile IDs are invalid. - Matching custom and built-in IDs are valid override behavior. - Raw `api_key` is rejected; use `api_key_env`. - If `api_key_env` is set, the named environment variable must be set before `run`, `render`, or HTTP execution can prepare the request. - Profile numeric fields merge by non-zero value. Request overrides are presence-aware, so explicit zero values are supported through CLI flags or HTTP model overrides. - `extra_params` keys must not be empty and must not collide with reserved outbound fields: `model`, `session_id`, `messages`, `temperature`, `max_tokens`, `top_p`, `service_tier`, `reasoning_effort`, or `response_format`. Built-in profile catalog: | Provider | ID | Model | API key env | | --- | --- | --- | --- | | aion-labs | `aion-2` | `aion-labs/aion-2.0` | `OPENROUTER_API_KEY` | | anthropic | `claude-fable-latest` | `~anthropic/claude-fable-latest` | `OPENROUTER_API_KEY` | | anthropic | `claude-haiku-latest` | `~anthropic/claude-haiku-latest` | `OPENROUTER_API_KEY` | | anthropic | `claude-opus-latest` | `~anthropic/claude-opus-latest` | `OPENROUTER_API_KEY` | | anthropic | `claude-sonnet-latest` | `~anthropic/claude-sonnet-latest` | `OPENROUTER_API_KEY` | | deepseek | `deepseek-3-2` | `deepseek/deepseek-v3.2` | `OPENROUTER_API_KEY` | | deepseek | `deepseek-4-pro` | `deepseek/deepseek-v4-pro` | `OPENROUTER_API_KEY` | | google | `gemini-2-flash` | `google/gemini-2.5-flash` | `OPENROUTER_API_KEY` | | google | `gemini-2-flash-lite` | `google/gemini-2.5-flash-lite` | `OPENROUTER_API_KEY` | | google | `gemini-2-pro` | `google/gemini-2.5-pro` | `OPENROUTER_API_KEY` | | google | `gemini-3-flash-lite` | `google/gemini-3.1-flash-lite` | `OPENROUTER_API_KEY` | | google | `gemini-flash-latest` | `~google/gemini-flash-latest` | `OPENROUTER_API_KEY` | | google | `gemini-pro-latest` | `~google/gemini-pro-latest` | `OPENROUTER_API_KEY` | | google | `gemma-4-31b` | `google/gemma-4-31b-it:exacto` | `OPENROUTER_API_KEY` | | minimax | `minimax-m2` | `minimax/minimax-m2.5` | `OPENROUTER_API_KEY` | | minimax | `minimax-m3` | `minimax/minimax-m3` | `OPENROUTER_API_KEY` | | mistral | `mistral-large-2512` | `mistralai/mistral-large-2512` | `OPENROUTER_API_KEY` | | mistral | `mistral-medium-3-5` | `mistralai/mistral-medium-3-5` | `OPENROUTER_API_KEY` | | mistral | `mistral-small-3` | `mistralai/mistral-small-3.2-24b-instruct` | `OPENROUTER_API_KEY` | | mistral | `mistral-small-4` | `mistralai/mistral-small-2603` | `OPENROUTER_API_KEY` | | nvidia | `nemotron-3-ultra` | `nvidia/nemotron-3-ultra-550b-a55b` | `OPENROUTER_API_KEY` | | openai | `gpt-5-mini` | `openai/gpt-5.4-mini` | `OPENROUTER_API_KEY` | | openai | `gpt-5-nano` | `openai/gpt-5.4-nano` | `OPENROUTER_API_KEY` | ## Schema Behavior Schemas are JSON files, typically under `schema_dir`. Rules: - `output.validation_mode: json_schema` requires `output.schema_path`. - Relative `schema_path` values resolve from `schema_dir`. - Absolute `schema_path` values are used directly. - Nested schemas must be referenced by relative path; schemas are not searched recursively by basename. - Missing or invalid schema documents are runtime validation errors. - Invalid generated JSON produces validation status `failed`, not a runtime error. ## Artifact References Supported request input artifact reference types are: - `file` - `inline` CLI `run` and `render` create `file` references from `--input name=path`. HTTP `file` references require `server.artifact_root` or `serve --artifact-root`. Relative file URIs resolve under that root. Absolute paths and relative traversal outside the root are rejected by lexical checks. Symlinks inside the root are followed by the operating system, including symlinks that point outside the root. HTTP `inline` references do not require an artifact root. ## Secrets Handling - Keep secret values in environment variables. - Store only environment-variable names in `api_key_env`. - Do not put raw API keys in config, prompts, profiles, CLI arguments, examples, or HTTP request bodies. ## Maintained Examples - Minimal app config: `examples/config.yml` - Full app config: `examples/config.full.yml` - Prompt examples: `examples/prompts/` - Custom profile examples: `examples/profiles/` - Schema examples: `examples/schemas/` - Input fixtures: `examples/fixtures/` - Render script: `examples/render-markdown-summary.sh` - HTTP request-shape example: `examples/http-run.json` ## Integration References - [CLI reference](cli.md) - [HTTP API reference](api.md) - [Outbound OpenAI-compatible contract](integrations/openai-compatible-chat.md)