Refresh primary documentation references

This commit is contained in:
2026-07-05 03:02:11 +00:00
parent d5d7a222a4
commit 574f88bd6a
4 changed files with 287 additions and 207 deletions

View File

@@ -2,30 +2,32 @@
## Config Discovery And Precedence
Application settings are loaded in this order:
Application settings are resolved in this order:
1. Built-in defaults
1. built-in defaults
2. `config.yml` values
3. CLI overrides
When `--config` is not provided, Scriptorium searches for config files in this order:
When `--config` is omitted, Scriptorium searches:
1. `/usr/local/etc/scriptorium/config.yml`
2. `/etc/scriptorium/config.yml`
If neither file exists, Scriptorium continues with built-in defaults.
If neither file exists, Scriptorium uses built-in defaults. When
`--config <path>` is provided, that file must exist and decode successfully.
When `--config <path>` is provided, that file is required.
## Minimal App Config
## Minimal Working Config
```yaml
prompt_dir: ./examples/prompts
```
This is enough to use `run` and `render` when prompts select built-in profiles.
This is enough for `run` and `render` when selected prompts use built-in
profiles. Set `profile_dir` when prompts or requests use custom profiles.
## Production-Oriented App Config
The maintained repository example is `examples/config.yml`.
## Production-Oriented Config
```yaml
prompt_dir: /opt/scriptorium/prompts
@@ -43,57 +45,48 @@ defaults:
render_format: text
```
## App Config File (`config.yml`)
The maintained full example is `examples/config.full.yml`.
## App Config Reference
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 by `json_schema` validation.
- `server.addr` (optional): default listen address for `serve`.
- `server.artifact_root` (optional): base directory for HTTP `file` input references.
- `server.max_request_bytes` (optional): maximum HTTP request body size. `0` disables this limit.
- `server.max_artifact_bytes` (optional): maximum HTTP `file` input artifact size. `0` disables this limit.
- `server.max_response_bytes` (optional): maximum encoded HTTP response body size. `0` disables this limit.
- `defaults.render_format` (optional): default `render` output format (`text` or `json`).
| 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. |
Built-in defaults:
`server` fields:
- `schema_dir`: `.`
- `server.addr`: `:8080`
- `server.artifact_root`: unset; HTTP `file` input references are rejected until configured.
- `server.max_request_bytes`: `16777216` (16 MiB)
- `server.max_artifact_bytes`: `16777216` (16 MiB)
- `server.max_response_bytes`: `16777216` (16 MiB)
- `defaults.render_format`: `text`
| 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. |
Validation behavior:
`defaults` fields:
- Config decoding is strict; unknown YAML fields are rejected.
- HTTP size limit values must be greater than or equal to `0`.
- Raw API key fields are not supported in `config.yml`.
| Field | Default | Description |
| --- | --- | --- |
| `defaults.render_format` | `text` | Default `render` output format: `text` or `json`. |
HTTP artifact root behavior:
Config rules:
- `server.artifact_root` applies only to `serve`.
- HTTP `inline` input references work without an artifact root.
- HTTP `file` input references are resolved against `server.artifact_root` with lexical path checks.
- Relative traversal and absolute paths that are lexically outside the root are rejected.
- Symlinks inside the root are followed by the operating system, including symlinks that point outside the root. Do not make the artifact root writable by untrusted users.
- CLI `run` and `render` file inputs keep their normal direct filesystem path behavior.
HTTP size-limit behavior:
- The request limit covers the encoded JSON request body, including inline input bodies.
- The artifact limit covers HTTP `file` input artifacts read through `serve`.
- The response limit covers the final encoded JSON response, including generated artifact bodies and `raw_model_output` when requested.
- Limits apply only to HTTP `serve`; CLI `run` and `render` keep direct filesystem behavior.
- 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`, 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`.
Prompt definitions are YAML files anywhere under `prompt_dir`. Nested
directories are organizational; callers select prompts by YAML `id`, not file
path.
Example:
@@ -126,84 +119,76 @@ output:
repair_attempts: 0
```
Field reference:
Prompt fields:
- `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.
- `session_id` (optional): Go-template string for OpenRouter sticky-routing `session_id`; rendered from request vars.
- `inputs` (optional list): expected named inputs.
- `messages` (required list): prompt message templates.
- `output` (required object): output contract.
| 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)
- `required` (optional boolean)
- `content_type` (optional metadata)
- `description` (optional)
`messages[]` fields:
- `role` (required)
- `content` or `content_file` (exactly one is required)
- `cache_control` (optional object): provider prompt-cache metadata for this message
- 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.
- `content_file` is resolved relative to the prompt YAML file location.
- Nested prompt files keep the same relative `content_file` behavior; `./recap.user.md` next to `dnd/recap.yaml` resolves from `dnd/`.
- 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.
- Prompt YAML decoding is strict.
- Duplicate input names are invalid.
- Duplicate prompt IDs are invalid for a requested ID/version.
`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.
| Field | Required | Supported values |
| --- | --- | --- |
| `type` | yes | `ephemeral` |
| `ttl` | no | `1h` |
Example cache-controlled message:
`session_id` behavior:
```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.
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>"}`.
- 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:
- `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`.
| 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 behavior boundary:
Repair 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.
- 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
Scriptorium includes built-in execution profiles. Custom execution profiles are YAML files anywhere under `profile_dir`, including nested subdirectories.
Execution profiles are YAML files anywhere under `profile_dir`. Nested
directories are organizational; callers select profiles by YAML `id`, not file
path.
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`.
Scriptorium also ships built-in profiles. Custom profiles override built-ins
with the same ID.
Example:
@@ -220,36 +205,44 @@ service_tier: priority
reasoning_effort: medium
extra_params:
provider_route: primary
provider_options:
retry_budget: 2
```
Field reference:
Profile fields:
- `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`
- `service_tier` (optional): provider-specific request tier such as OpenRouter `flex` or `priority`
- `reasoning_effort` (optional): serialized as top-level `reasoning_effort` in outbound chat-completions requests
- `api_key_env` (optional)
- `extra_params` (optional map): JSON-compatible provider-specific parameters. Values may be strings, numbers, booleans, objects, or arrays.
| 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_dir` is optional. If omitted, only built-in profiles are available.
- If `profile_dir` is set, custom profiles from that directory override built-in profiles with the same `id`.
- 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.
- 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, 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_params` keys 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`, or `response_format`.
- 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 IDs:
Built-in profile catalog:
| Provider | ID | Model | API key env |
| --- | --- | --- | --- |
@@ -277,56 +270,55 @@ Built-in profile IDs:
| 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`, optional `session_id`, `messages`, `temperature`, `max_tokens`, `top_p`, `service_tier`, `reasoning_effort`, optional `response_format` for `json_schema` prompts, and `extra_params`.
- `extra_params` are flattened into provider-specific top-level JSON request fields. They are not wrapped in an `extra_params` object on the outbound provider request.
- Messages without `cache_control` serialize with string `content`.
- Messages with `cache_control` serialize as a single text content-block array containing `cache_control`.
## Schema Behavior
Schemas are JSON files, typically in `schema_dir`.
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`, including explicit nested paths such as `dnd/structured_events.schema.json`.
- Relative `schema_path` values resolve from `schema_dir`.
- Absolute `schema_path` values 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).
- 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.
Supported artifact reference types for request inputs are `file` and `inline`.
For HTTP `serve`, `file` references require `server.artifact_root` and must pass
lexical containment checks against that root. CLI `run` and `render` file inputs
are not restricted by `server.artifact_root`.
## 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 profile `api_key_env`.
- Do not put raw API keys in config, prompts, profiles, CLI flags, or HTTP request bodies.
- 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
- App config: `examples/config.yml`
- 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 example script: `examples/render-markdown-summary.sh`
- HTTP request example: `examples/http-run.json`
Example organizational layout:
```text
examples/prompts/dnd/recap.yaml
examples/profiles/local/local-quality.yaml
examples/schemas/dnd/structured_events.schema.json
```
- 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)