scriptorium
Scriptorium is a generic prompt execution engine.
It takes:
- a prompt definition
- a selected or default execution profile
- named input artifacts
- template variables
- optional runtime overrides
It returns:
- for
run: generated artifact, validation result, metadata - for
render: prepared/rendered prompt data (no model output)
Prompt vs Profile
Scriptorium separates what to do (Prompt) from how to do it (Profile).
Prompt Definition
Defines the task logic and output contract.
- Task description and version.
- Message templates (system, user, etc.).
- Required and optional input artifacts.
- Output format and validation rules.
- Repair settings for structured output.
- Optional
default_profilefor convenience.
Execution Profile
Defines the runtime environment and model settings.
- LLM endpoint (URL).
- Model name.
- Generation parameters:
temperature,max_tokens,top_p. - Runtime settings:
timeout,reasoning_effort. - API key source via
api_key_env.
Callers can explicitly provide a profile_id to override the prompt's default_profile.
Precedence
Scriptorium uses two precedence layers:
Application Configuration Precedence
For application-level adapter settings (for example prompt/profile/schema directories, server address, and render output default), precedence is:
- CLI Flags
config.yml- Built-in application defaults
Application config loading behavior:
- Default config path:
/etc/scriptorium/config.yml - Override path:
--config <PATH>(supported byrun,render, andserve) - If
--configis provided, the file must exist and be valid. - If
--configis omitted, missing/etc/scriptorium/config.ymlis allowed.
Runtime Model Precedence
When resolving runtime model settings, Scriptorium follows this precedence model (highest to lowest):
- Runtime Overrides: Provided via CLI flags or HTTP request
modelobject. - Execution Profile: Settings defined in the selected profile.
- Application Defaults: Built-in fallback values.
Profile Selection Logic
The engine determines which profile to use in this order:
- Explicit
profile_id(via--profileor HTTP request). - The
default_profilenamed in the Prompt Definition. - Error: If neither is provided and no default exists.
API Key Policy
To ensure security, Scriptorium does not support raw API keys in configuration files, CLI arguments, or HTTP requests.
api_key_env: Profiles and overrides specify the name of an environment variable (e.g.,SCRIPTORIUM_API_KEY).- Runtime Resolution: The value of the environment variable is read directly from the process environment at runtime.
- Zero Leakage: API key values are never included in metadata, logs, or response bodies.
CLI Usage
Available CLI commands:
scriptorium runscriptorium renderscriptorium serve
All commands accept --config <PATH>.
prompt_dir and profile_dir may be supplied by CLI flags or config.yml:
--prompt-dirorconfig.ymlprompt_dir--profile-dirorconfig.ymlprofile_dir
schema_dir and serve addr may also be supplied by config.yml where applicable:
--schema-dirorconfig.ymlschema_dir--addrorconfig.ymlserver.addr
scriptorium run
Runs a single prompt execution.
Required Flags:
--prompt: The prompt ID to execute.--input: Input mappingname=path(repeatable).
Required Effective Settings:
- Prompt directory:
--prompt-dirorconfig.ymlprompt_dir - Profile directory:
--profile-dirorconfig.ymlprofile_dir
Optional Flags:
--config: Application config file path. Default discovery path is/etc/scriptorium/config.yml.--prompt-dir: Override prompt directory from config.--profile-dir: Override profile directory from config.--profile: Override the prompt's default profile.--var: Template variablename=value(repeatable).--out: Write output to a file instead of stdout.--llm-base-url: Override endpoint.--model: Override model name.--api-key-env: Override API key environment variable name.--temperature: Override temperature.--max-tokens: Override max tokens.--top-p: Override top_p.--timeout: Override request timeout (e.g.,30s,1m).--schema-dir: Base directory for validation schemas.
Examples:
Using config.yml for prompt/profile directories:
scriptorium run \
--prompt generic.markdown_summary \
--input transcript=./examples/fixtures/transcript.md
Overriding config directories explicitly:
scriptorium run \
--prompt-dir ./prompts \
--profile-dir ./profiles \
--prompt generic.markdown_summary \
--input transcript=./examples/fixtures/transcript.md
Overriding the profile:
scriptorium run \
--prompt-dir ./prompts \
--profile-dir ./profiles \
--prompt generic.markdown_summary \
--profile local-quality \
--input transcript=./examples/fixtures/transcript.md
Overriding model and runtime values:
scriptorium run \
--prompt-dir ./prompts \
--profile-dir ./profiles \
--prompt generic.markdown_summary \
--model gpt-4o \
--temperature 0.7 \
--input transcript=./examples/fixtures/transcript.md
Using a local OpenAI-compatible vLLM endpoint:
scriptorium run \
--prompt-dir ./prompts \
--profile-dir ./profiles \
--prompt generic.markdown_summary \
--llm-base-url http://localhost:8000/v1 \
--model meta-llama-3-8b \
--input transcript=./examples/fixtures/transcript.md
scriptorium render
Prepares and renders a prompt without calling the LLM.
render uses the same prompt/profile/input/variable/runtime override resolution as run:
- Profile selection precedence:
--profile-> promptdefault_profile-> error. - Runtime precedence: CLI runtime overrides -> selected profile -> built-in defaults.
render is useful for debugging:
- prompt template rendering
- input mappings
- selected profile behavior
- runtime override behavior
render does not:
- call the LLM
- validate model output
- perform repair
- expose resolved API key values
It may include api_key_env names where relevant.
Required Flags:
--prompt: The prompt ID to render.--input: Input mappingname=path(repeatable).
Required Effective Settings:
- Prompt directory:
--prompt-dirorconfig.ymlprompt_dir - Profile directory:
--profile-dirorconfig.ymlprofile_dir
Optional Flags:
--config: Application config file path. Default discovery path is/etc/scriptorium/config.yml.--prompt-dir: Override prompt directory from config.--profile-dir: Override profile directory from config.--profile: Override the prompt's default profile.--var: Template variablename=value(repeatable).--out: Write output to a file instead of stdout.--format: Render output format (textorjson). Default:text.--llm-base-url: Runtime override for endpoint.--model: Runtime override for model name.--api-key-env: Runtime override for API key environment variable name.--temperature: Runtime override for temperature.--max-tokens: Runtime override for max tokens.--top-p: Runtime override for top_p.--timeout: Runtime override for timeout (e.g.,30s,1m).
Render Output Formats:
text: Human-readable output (default).json: Machine-readable structured output.
Render formatting is modular; additional output formats can be added later without changing prepare/run core logic.
Examples:
Default text output using config.yml directories:
scriptorium render \
--prompt generic.markdown_summary \
--input transcript=./examples/fixtures/transcript.md
Explicit config path:
scriptorium render \
--config ./examples/config.yml \
--prompt generic.markdown_summary \
--input transcript=./examples/fixtures/transcript.md
Explicit directory overrides:
scriptorium render \
--prompt-dir ./prompts \
--profile-dir ./profiles \
--prompt generic.markdown_summary \
--input transcript=./examples/fixtures/transcript.md
Explicit JSON output:
scriptorium render \
--prompt-dir ./prompts \
--profile-dir ./profiles \
--prompt generic.markdown_summary \
--input transcript=./examples/fixtures/transcript.md \
--format json
Using prompt default_profile (omit --profile):
scriptorium render \
--prompt-dir ./prompts \
--profile-dir ./profiles \
--prompt generic.markdown_summary \
--input transcript=./examples/fixtures/transcript.md
Overriding profile selection:
scriptorium render \
--prompt-dir ./prompts \
--profile-dir ./profiles \
--prompt generic.markdown_summary \
--profile local-quality \
--input transcript=./examples/fixtures/transcript.md
Overriding runtime settings:
scriptorium render \
--prompt-dir ./prompts \
--profile-dir ./profiles \
--prompt generic.markdown_summary \
--input transcript=./examples/fixtures/transcript.md \
--llm-base-url http://localhost:8000/v1 \
--model gpt-4o-mini \
--temperature 0.2 \
--max-tokens 800 \
--top-p 1.0 \
--timeout 45s
Writing rendered output to a file:
scriptorium render \
--prompt-dir ./prompts \
--profile-dir ./profiles \
--prompt generic.markdown_summary \
--input transcript=./examples/fixtures/transcript.md \
--format text \
--out ./rendered_prompt.txt
scriptorium serve
Starts the HTTP API.
Required Effective Settings:
- Prompt directory:
--prompt-dirorconfig.ymlprompt_dir - Profile directory:
--profile-dirorconfig.ymlprofile_dir
Optional Flags:
--config: Application config file path. Default discovery path is/etc/scriptorium/config.yml.--addr: Listen address (default:8080).--schema-dir: Base directory for validation schemas.
Examples:
Using config.yml:
scriptorium serve
Overriding config for local use:
scriptorium serve \
--prompt-dir ./prompts \
--profile-dir ./profiles \
--addr :9090
HTTP API
POST /v1/runs
Executes a prompt. No built-in authentication is provided; deploy behind a trusted gateway.
Request Body:
{
"prompt_id": "generic.structured_events",
"profile_id": "local-quality",
"include_raw_output": false,
"inputs": {
"transcript": {"type": "file", "uri": "./examples/fixtures/transcript.md"}
},
"vars": {
"session_date": "2026-05-04"
},
"model": {
"endpoint": "http://localhost:8000/v1",
"model": "gpt-4o-mini",
"temperature": 0.0
}
}
profile_id is optional. If omitted, Scriptorium uses the prompt's default_profile. If neither is available, the run fails.
Response:
Returns a 200 OK with the generated artifact, validation results, and metadata including the prompt_id and the selected_profile_id.
Validation Failures:
If the model output fails validation (e.g., invalid JSON), the API returns 200 OK with validation.status = "failed".
Raw Output Exposure:
raw_model_outputis omitted by default.- Set
include_raw_output: truein the request to include it in the response. - Raw output is preserved internally in run results regardless of HTTP exposure.
Prompt Definition Authoring
Prompts are defined in YAML.
Canonical Shape
id: generic.structured_events
version: "1.0.0"
description: "Extracts structured events from a transcript"
default_profile: local-quality
inputs:
- name: transcript
required: true
content_type: text/markdown
description: "The raw session transcript"
- name: glossary
required: false
content_type: application/yaml
description: "Optional glossary terms"
messages:
- role: system
content: "You are a helpful assistant."
- role: user
content_file: messages/extract_events.tmpl
output:
format: json
validation_mode: json_schema
schema_path: structured_events.schema.json
repair_attempts: 2
Key Features:
- Inline vs File: Use
contentfor short prompts orcontent_filefor larger templates. Exactly one must be set per message. - Path Resolution:
content_filepaths are resolved relative to the prompt YAML file. - Inputs: Mark inputs as
requiredto ensure the runner fails early if they are missing. - Input Metadata:
content_typeis currently descriptive metadata and not enforced yet. - Validation: Support
none,basic,json, andjson_schema. - Repair:
repair_attemptsenables bounded retries to fix structured output.
Execution Profile Authoring
Profiles are defined in YAML.
Canonical Shape
id: local-quality
endpoint: http://localhost:8000/v1
model: gpt-4o
temperature: 0.0
max_tokens: 4096
top_p: 1.0
timeout_seconds: 300
reasoning_effort: high
api_key_env: SCRIPTORIUM_API_KEY
Constraints:
- No Raw Keys: Do not include actual API keys. Only specify the environment variable name in
api_key_env. - Local Profiles: For local endpoints that don't require auth,
api_key_envcan be omitted.
Examples
- Prompt Definitions:
prompts/ - Execution Profiles:
profiles/ - Schemas:
schemas/ - Fixtures:
examples/fixtures/
Build and Test
go build -o scriptorium ./cmd/scriptorium
go test ./...