Skip to content

Capability: configuration ​

One TOML file validated into typed models that reject unknown keys; every secret from the environment only; one CLI that fails to start with the missing variable's name; Temporal either remote or embedded, from the same file.

What it is ​

How a deployment is described and how the processes come up. Lives in tiny_harness/config.py, tiny_harness/service/cli.py, commands.py and runtime.py.

Current behaviour ​

  • Settings SHALL be the sections temporal, openai, anthropic (optional), server, heartbeat, plugins, agents, card, store, o11y, retries, context and retention, every model extra="forbid".
  • [server] delegators SHALL list the participant ids trusted to set lifecycle, model and reasoning_effort on a new task's first message; this agent's own id is always trusted. agents[].id SHALL NOT be self, the harness's own agent id (issue-34 R7).
  • [card] SHALL take an optional name, description and version and a list of [[card.skills]] (id, name, description, tags, examples). A set string SHALL not be blank, and skill ids SHALL be unique; otherwise startup exits with status 2. An absent section or key keeps the built-in default (issue-34).
  • Each agents entry SHALL take id, url, version and, from issue-27, updates (auto, follow or off; default auto) and follow_interval (default 5 s, at least 1 s); any other updates value, or a shorter interval, exits with status 2 naming agents.<n>.<key>.
  • [temporal] mode SHALL be remote (the default) or embedded; any other value exits with status 2 naming temporal.mode. Remote mode requires address, namespace and TEMPORAL_API_KEY and refuses [temporal.embedded]; embedded mode refuses address, tls and TEMPORAL_API_KEY, defaults namespace to default, and takes the optional [temporal.embedded] table (persist, database_path, binary_path, download_dir, port). A binary_path that is not an executable file exits with status 2.
  • [openai] and [anthropic] SHALL also take models (the models /model may select; unset means model alone) and reasoning_effort (low, medium or high; the default effort, unset means none is sent). A models list that is empty or lacks model SHALL exit with status 2 naming openai.models, never "any model allowed".
  • [openai] SHALL take base_url (an absolute http/https URL; default https://api.openai.com/v1), api (responses or chat_completions), model, timeout, max_output_tokens and context_window_tokens (a positive integer; a boolean or a float is refused). OPENAI_API_KEY SHALL be required only when base_url is unset. A base_url with user information, or with http to a non-loopback host while a key is set (loopback is localhost or a literal loopback address, never resolved), SHALL exit with status 2 naming openai.base_url.
  • Secrets SHALL come only from TEMPORAL_API_KEY (remote mode only), OPENAI_API_KEY, and ANTHROPIC_API_KEY, LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY (when their features are configured), held as SecretStr and never printed; the configured values are what the redactor masks.
  • TINY_HARNESS_PUSH_KEY SHALL NOT be read; WHEN it is set THEN the runtime SHALL log one WARNING that it is set and ignored, without its value (as for OPENAI_BASE_URL).
  • WHEN a required secret is missing or a key is unknown THEN the process SHALL exit with status 2 and the variable or key on stderr, with no anonymous or local fallback.
  • The CLI SHALL be tiny-harness [--config FILE] [serve [--with-worker] | worker | tui [--url] [--participant] | schedules delete | tasks purge <task-id>]; with no subcommand it SHALL run tui with no --url. --version prints the package version and --help names the configuration file in effect and whether it came from --config or the default location (--help never creates it).
  • The configuration file SHALL be --config when given, else ~/.tiny-harness/config.toml (tiny_harness/home.py), for every subcommand. With --config the home directory is never read or created, and a missing file exits 2. WHEN the default file is missing THEN the CLI SHALL create ~/.tiny-harness/ (mode 0700) and the file (0600, O_EXCL | O_NOFOLLOW, through a no-follow directory descriptor), print created default configuration <path> on stderr and go on. The file selects embedded Temporal with persist = true, puts the store (and so the Temporal database and the TUI log) under the home with absolute paths, holds no secret and comments every key. An existing file is never rewritten. A home or file that is a symlink, not a directory or regular file, or owned by another user SHALL exit 2 naming the path; there is no fallback to running without a file.
  • In embedded mode, worker SHALL exit 2 (the worker runs inside serve), serve SHALL run the worker in-process, tui with no --url SHALL host the harness in its own process (logs to tiny-harness.log beside the store), and schedules delete / tasks purge SHALL act on the persisted state, exiting 2 when persist = false. A dev server that fails to start SHALL exit 1 with the cause. SIGTERM SHALL cancel the main task so every finally runs: serve (and the programmatic serve) then exits 0, the other commands 143 (tiny_harness/service/signals.py).
  • tiny_harness.service SHALL export the programmatic entry points running_harness, serve, RunningHarness, temporal_client and complete_message, driven by the same Settings as the CLI. running_harness takes plugins= (paths or Plugin objects, loaded after settings.plugins with override), commands= ((CommandSpec, handler) pairs) and builtin_commands=False. Settings.load and the entry points SHALL NOT read or create ~/.tiny-harness/; tiny_harness.home.resolve_config_path and ensure_default_config are what the CLI calls, public for an SDK caller.
  • [agent] SHALL name the agent: id (lowercase, digits and -, default tiny-harness). The card's name and description stay in [card]. [temporal] task_queue SHALL default to agent.id. A file without either keeps the id and queue tiny-harness.
  • tiny_harness.service SHALL also export Harness, harnesses_lifespan and RouteOptions. pip install 'tiny_harness[fastapi]' adds tiny_harness.fastapi, whose import without FastAPI names the extra.
  • build_runtime SHALL assemble one process from Settings: the built-in plugin, the operator's plugins, the MCP tool sources, the skills, the system prompt, the model, the store and the in-process engine the activities run over, with the plugin data root at plugin-data/ beside the store. self SHALL carry the harness's public_url. A remote agent whose URL is a harness of this process SHALL get that harness's card built from its settings, not fetched.
  • The demo configuration SHALL document the keyring lookups secret-tool lookup service temporal project tiny-harness and secret-tool lookup service openai project tiny-harness.

Design ​

design.md § Configuration, deploy guide, configuration.

History ​

Work itemWhat changedLinks
issue-3Settings, secrets, errors (Layer 1); the CLI and runtime (Layer 5); trace_file, search_attributes, ui_dir, cors_origins (Layers 8–9)spec, PR #7, PR #11
issue-17temporal.mode and [temporal.embedded]; per-command embedded behaviour; the programmatic API in tiny_harness.service; SIGTERM cancels the main taskspec, PR #18, decision-005
issue-19[openai] base_url, api, context_window_tokens; OPENAI_API_KEY optional with a base_url; examples/demo/config.ollama.tomlspec, PR #22, decision-006
issue-23TINY_HARNESS_PUSH_KEY and Settings.push_key removed; a set variable is reported as ignoredspec, PR #24
issue-25The default file ~/.tiny-harness/config.toml (created safely, --config wins); bare tiny-harness runs the TUI; --help names the file; models and reasoning_effort; running_harness(plugins=, commands=, builtin_commands=) and complete_messagespec, PR #26, decision-007
issue-27agents[].updates and agents[].follow_intervalspec, PR #28
issue-34[card]: this agent's own card name, description, version and skillsspec, PR #35
issue-34 (R7)[server] delegators; the agent id self reservedspec, PR #35
issue-36[agent]; the task queue defaults to the agent id; Harness, harnesses_lifespan, RouteOptions exported; the fastapi extraspec, PR #37, decision-009