2026-05-26 03:21:11 +00:00
# Configuration Reference
## Config Discovery And Precedence
Application settings are loaded in this order:
1. Built-in defaults
2. `config.yml` values
3. CLI overrides
When `--config` is not provided, Scriptorium searches for config files in this order:
1. `/usr/local/etc/scriptorium/config.yml`
2. `/etc/scriptorium/config.yml`
If neither file exists, Scriptorium continues with built-in defaults.
When `--config <path>` is provided, that file is required.
## Minimal App Config
```yaml
2026-05-26 07:15:36 -05:00
prompt_dir: ./examples/prompts
profile_dir: ./examples/profiles
2026-05-26 03:21:11 +00:00
```
This is enough to use `run` and `render` when prompt/profile files are valid.
## Production-Oriented App Config
```yaml
prompt_dir: /opt/scriptorium/prompts
profile_dir: /opt/scriptorium/profiles
schema_dir: /opt/scriptorium/schemas
server:
addr: 127.0.0.1:8080
defaults:
render_format: text
```
## App Config File (`config.yml`)
Top-level fields:
- `prompt_dir` (optional): default prompt definition directory.
- `profile_dir` (optional): default profile definition directory.
- `schema_dir` (optional): base directory for schema files used by `json_schema` validation.
- `server.addr` (optional): default listen address for `serve` .
- `defaults.render_format` (optional): default `render` output format (`text` or `json` ).
Built-in defaults:
- `schema_dir` : `.`
- `server.addr` : `:8080`
- `defaults.render_format` : `text`
Validation behavior:
- Config decoding is strict; unknown YAML fields are rejected.
- Raw API key fields are not supported in `config.yml` .
## Prompt Definition Files
2026-05-26 07:36:10 -05:00
Prompt definitions are YAML files anywhere under `prompt_dir` , including nested subdirectories.
Subdirectories are organizational only. Callers still select prompts by the YAML `id` , not by file path. For example, `prompts/dnd/recap.yaml` may still declare `id: dnd.recap` , and callers use `--prompt dnd.recap` .
2026-05-26 03:21:11 +00:00
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
```
Field reference:
- `id` (required): prompt identifier.
- `version` (required): prompt version.
- `default_profile` (optional): profile ID used when request does not provide `profile_id` .
- `description` (optional): prompt description.
2026-07-02 20:08:44 -05:00
- `session_id` (optional): Go-template string for OpenRouter sticky-routing `session_id` ; rendered from request vars.
2026-05-26 03:21:11 +00:00
- `inputs` (optional list): expected named inputs.
- `messages` (required list): prompt message templates.
- `output` (required object): output contract.
`inputs[]` fields:
- `name` (required)
- `required` (optional, boolean)
- `content_type` (optional metadata)
- `description` (optional)
`messages[]` fields:
- `role` (required)
- `content` or `content_file` (exactly one is required)
2026-07-02 23:10:24 +00:00
- `cache_control` (optional object): provider prompt-cache metadata for this message
2026-05-26 03:21:11 +00:00
Message rules:
- Repeated roles are allowed.
- `content_file` is resolved relative to the prompt YAML file location.
2026-05-26 07:36:10 -05:00
- Nested prompt files keep the same relative `content_file` behavior; `./recap.user.md` next to `dnd/recap.yaml` resolves from `dnd/` .
2026-05-26 03:21:11 +00:00
- Prompt decoding is strict; unknown YAML fields are rejected.
2026-05-26 07:36:10 -05:00
- Duplicate prompt IDs are invalid. If multiple files declare the requested prompt ID, Scriptorium fails instead of choosing one.
2026-05-26 03:21:11 +00:00
2026-07-02 23:10:24 +00:00
`messages[].cache_control` fields:
- `type` (required when `cache_control` is present): currently only `ephemeral` .
- `ttl` (optional): currently only `1h` ; omitted from outbound requests when unset.
Example cache-controlled message:
```yaml
messages:
- role: system
content_file: ./stable_context.md
cache_control:
type: ephemeral
ttl: 1h
- role: user
content: |
{{input "transcript"}}
```
Use cache control on stable reusable prompt content. Dynamic per-run inputs before the cache-controlled message change the provider cache key.
2026-07-02 20:08:44 -05:00
Example prompt-level session ID:
```yaml
session_id: "{{ .session_id }}"
```
When configured, `session_id` is rendered with the same variable context as messages. The rendered value is trimmed, omitted when empty, and rejected if longer than 256 characters. CLI callers pass the value through `--var session_id=<value>` ; HTTP callers pass it through `"vars": {"session_id": "<value>"}` .
2026-05-26 03:21:11 +00:00
`output` fields:
- `format` (required): `text` , `markdown` , or `json` .
- `validation_mode` (required): `none` , `basic` , `json` , or `json_schema` .
- `schema_path` (required when `validation_mode: json_schema` ).
- `repair_attempts` (required): integer `>= 0` .
Repair behavior boundary:
- `repair_attempts` is part of the prompt contract.
- CLI and HTTP currently construct the runner without a repairer, so normal `run` /`serve` execution does not perform output repair attempts.
## Profile Definition Files
2026-05-26 07:36:10 -05:00
Execution profiles are YAML files anywhere under `profile_dir` , including nested subdirectories.
Subdirectories are organizational only. Callers still select profiles by the YAML `id` , not by file path. For example, `profiles/local/local-quality.yaml` may still declare `id: local-quality` , and callers use `--profile local-quality` .
2026-05-26 03:21:11 +00:00
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
2026-05-26 07:44:49 -05:00
service_tier: priority
2026-05-26 03:21:11 +00:00
```
Field reference:
- `id` (required)
- `endpoint` (required)
- `model` (required)
- `temperature` (optional): range `0..2`
- `max_tokens` (optional): `>= 0`
- `top_p` (optional): range `0..1`
- `timeout_seconds` (optional): `>= 0`
2026-05-26 07:44:49 -05:00
- `service_tier` (optional): provider-specific request tier such as OpenRouter `flex` or `priority`
2026-05-26 03:21:11 +00:00
- `reasoning_effort` (optional)
- `api_key_env` (optional)
- `extra_params` (optional map of strings)
Profile rules:
- Profile decoding is strict; unknown YAML fields are rejected.
- Raw `api_key` is rejected; use `api_key_env` .
- If `api_key_env` is set, that environment variable must be set when preparing/running.
2026-05-26 07:36:10 -05:00
- Duplicate profile IDs are invalid. If multiple files declare the requested profile ID, Scriptorium fails instead of choosing one.
2026-05-26 03:21:11 +00:00
Current outbound request behavior:
2026-07-02 20:08:44 -05:00
- The OpenAI-compatible client currently serializes: `model` , optional `session_id` , `messages` , `temperature` , `max_tokens` , `top_p` , `service_tier` , and optional `response_format` for `json_schema` prompts.
2026-07-02 23:10:24 +00:00
- Messages without `cache_control` serialize with string `content` .
- Messages with `cache_control` serialize as a single text content-block array containing `cache_control` .
2026-05-26 03:21:11 +00:00
- `reasoning_effort` and `extra_params` are parsed and carried in effective settings, but are not currently serialized into outbound chat-completions requests.
## Schema Behavior
Schemas are JSON files, typically in `schema_dir` .
Rules:
- `output.validation_mode: json_schema` requires `output.schema_path` .
2026-05-26 07:36:10 -05:00
- Relative `schema_path` values resolve from `schema_dir` , including explicit nested paths such as `dnd/structured_events.schema.json` .
2026-05-26 03:21:11 +00:00
- Absolute `schema_path` values are used directly.
2026-05-26 07:36:10 -05:00
- Scriptorium does not recursively search schemas by basename; nested schemas must be referenced by their relative path.
2026-05-26 03:21:11 +00:00
- Missing or invalid schema documents cause runtime validation errors.
- Invalid generated JSON causes validation status `failed` (not a runtime error).
Supported artifact reference types for request inputs are `file` and `inline` .
## Secrets Handling
- Keep secret values in environment variables.
- Store only environment-variable names in profile `api_key_env` .
- Do not put raw API keys in config, prompts, profiles, CLI flags, or HTTP request bodies.
## Maintained Examples
- App config: `examples/config.yml`
2026-05-26 07:15:36 -05:00
- Prompt examples: `examples/prompts/`
- Profile examples: `examples/profiles/`
- Schema examples: `examples/schemas/`
2026-05-26 03:21:11 +00:00
- Input fixtures: `examples/fixtures/`
2026-05-26 03:33:25 +00:00
- Render example script: `examples/render-markdown-summary.sh`
- HTTP request example: `examples/http-run.json`
2026-05-26 03:31:01 +00:00
2026-05-26 07:36:10 -05:00
Example organizational layout:
```text
examples/prompts/dnd/recap.yaml
examples/profiles/local/local-quality.yaml
examples/schemas/dnd/structured_events.schema.json
```
2026-05-26 03:31:01 +00:00
## Integration References
2026-05-26 07:15:36 -05:00
- [Inbound HTTP contract ](integrations/http-api.md )
- [Outbound OpenAI-compatible contract ](integrations/openai-compatible-chat.md )