12 KiB
Configuration Reference
Config Discovery And Precedence
Application settings are loaded in this order:
- Built-in defaults
config.ymlvalues- CLI overrides
When --config is not provided, Scriptorium searches for config files in this order:
/usr/local/etc/scriptorium/config.yml/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
prompt_dir: ./examples/prompts
This is enough to use run and render when prompts select built-in profiles.
Production-Oriented App Config
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 custom profile definition directory.schema_dir(optional): base directory for schema files used byjson_schemavalidation.server.addr(optional): default listen address forserve.defaults.render_format(optional): defaultrenderoutput format (textorjson).
Built-in defaults:
schema_dir:.server.addr::8080defaults.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
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.
Example:
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 provideprofile_id.description(optional): prompt description.session_id(optional): Go-template string for OpenRouter sticky-routingsession_id; rendered from request vars.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)contentorcontent_file(exactly one is required)cache_control(optional object): provider prompt-cache metadata for this message
Message rules:
- Repeated roles are allowed.
content_fileis resolved relative to the prompt YAML file location.- Nested prompt files keep the same relative
content_filebehavior;./recap.user.mdnext todnd/recap.yamlresolves fromdnd/. - Prompt decoding is strict; unknown YAML fields are rejected.
- Duplicate prompt IDs are invalid. If multiple files declare the requested prompt ID, Scriptorium fails instead of choosing one.
messages[].cache_control fields:
type(required whencache_controlis present): currently onlyephemeral.ttl(optional): currently only1h; omitted from outbound requests when unset.
Example cache-controlled message:
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.
Example prompt-level session ID:
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>"}.
output fields:
format(required):text,markdown, orjson.validation_mode(required):none,basic,json, orjson_schema.schema_path(required whenvalidation_mode: json_schema).repair_attempts(required): integer>= 0.
Repair behavior boundary:
repair_attemptsis part of the prompt contract.- CLI and HTTP currently construct the runner without a repairer, so normal
run/serveexecution does not perform output repair attempts.
Profile Definition Files
Scriptorium includes built-in execution profiles. Custom 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.
Example:
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
provider_options:
retry_budget: 2
Field reference:
id(required)endpoint(required)model(required)temperature(optional): range0..2max_tokens(optional):>= 0top_p(optional): range0..1timeout_seconds(optional):>= 0service_tier(optional): provider-specific request tier such as OpenRouterflexorpriorityreasoning_effort(optional): serialized as top-levelreasoning_effortin outbound chat-completions requestsapi_key_env(optional)extra_params(optional map): JSON-compatible provider-specific parameters. Values may be strings, numbers, booleans, objects, or arrays.
Profile rules:
profile_diris optional. If omitted, only built-in profiles are available.- If
profile_diris set, custom profiles from that directory override built-in profiles with the sameid. - Duplicate IDs within the custom profile directory are invalid. Matching IDs across custom and built-in profiles are valid override behavior.
- Profile decoding is strict; unknown YAML fields are rejected.
- Raw
api_keyis rejected; useapi_key_env. - If
api_key_envis set, that environment variable must be set when preparing/running. - Duplicate profile IDs are invalid. If multiple files declare the requested profile ID, Scriptorium fails instead of choosing one.
extra_paramskeys must not be empty and must not collide with reserved outbound request fields:model,session_id,messages,temperature,max_tokens,top_p,service_tier,reasoning_effort, orresponse_format.
Built-in profile IDs:
| 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 |
gemini-2-flash |
google/gemini-2.5-flash |
OPENROUTER_API_KEY |
|
gemini-2-flash-lite |
google/gemini-2.5-flash-lite |
OPENROUTER_API_KEY |
|
gemini-2-pro |
google/gemini-2.5-pro |
OPENROUTER_API_KEY |
|
gemini-3-flash-lite |
google/gemini-3.1-flash-lite |
OPENROUTER_API_KEY |
|
gemini-flash-latest |
~google/gemini-flash-latest |
OPENROUTER_API_KEY |
|
gemini-pro-latest |
~google/gemini-pro-latest |
OPENROUTER_API_KEY |
|
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 |
Current outbound request behavior:
- The OpenAI-compatible client currently serializes:
model, optionalsession_id,messages,temperature,max_tokens,top_p,service_tier,reasoning_effort, optionalresponse_formatforjson_schemaprompts, andextra_params. extra_paramsare flattened into provider-specific top-level JSON request fields. They are not wrapped in anextra_paramsobject on the outbound provider request.- Messages without
cache_controlserialize with stringcontent. - Messages with
cache_controlserialize as a single text content-block array containingcache_control.
Schema Behavior
Schemas are JSON files, typically in schema_dir.
Rules:
output.validation_mode: json_schemarequiresoutput.schema_path.- Relative
schema_pathvalues resolve fromschema_dir, including explicit nested paths such asdnd/structured_events.schema.json. - Absolute
schema_pathvalues are used directly. - Scriptorium does not recursively search schemas by basename; nested schemas must be referenced by their relative path.
- 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 - Prompt examples:
examples/prompts/ - Custom profile examples:
examples/profiles/ - Schema examples:
examples/schemas/ - Input fixtures:
examples/fixtures/ - Render example script:
examples/render-markdown-summary.sh - HTTP request example:
examples/http-run.json
Example organizational layout:
examples/prompts/dnd/recap.yaml
examples/profiles/local/local-quality.yaml
examples/schemas/dnd/structured_events.schema.json