Configure Jidoka with a small set of application defaults. Provider keys stay in the process environment, where ReqLLM reads them at call time.
When To Use This
- Use this guide when you want to change the default model, generation parameters, loop budget, or turn timeout for a host application.
- Use this guide as a reference when wiring
:jidokainto a Phoenix or umbrella project for the first time. - Do not use this guide for per-agent configuration; those values live in the DSL or in the imported spec. See Agent DSL.
- Do not use this guide as a credential-management primer. Jidoka does not own provider auth; that is ReqLLM's responsibility.
Prerequisites
- A working Jidoka DSL agent. See Getting Started.
- A
config/config.exs(and ideallyconfig/runtime.exs) in the host application. - For live turns: provider credentials available in the runtime environment.
Quick Example
A minimal config/config.exs for a Jidoka-backed application:
import Config
config :jidoka,
default_model: "openai:gpt-4o-mini",
default_max_model_turns: 8,
default_turn_timeout_ms: 30_000,
default_generation: %{
params: %{
temperature: 0.0,
max_tokens: 500
}
}
import_config "#{config_env()}.exs"Jidoka.Config reads these keys on first use; agents that do not specify
their own model, generation, max_model_turns, or timeout_ms fall
through to these values.
Concepts
╭───────────────────────────╮
│ config/config.exs │
│ config :jidoka, ... │
╰─────────────┬─────────────╯
│ Application.get_env(:jidoka, key)
▼
╭───────────────────────────╮
│ Jidoka.Config │
│ default_model │
│ default_generation │
│ default_max_model_turns │
│ default_turn_timeout_ms │
╰─────────────┬─────────────╯
│ used by
▼
╭───────────────────────────╮ ╭───────────────────────────╮
│ Jidoka.Agent.Spec │ │ Turn.Plan defaults │
│ (when DSL omits values) │ │ (loop + timeout budget) │
╰───────────────────────────╯ ╰───────────────────────────╯
╭───────────────────────────╮
│ Process environment │
│ OPENAI_API_KEY │
│ ANTHROPIC_API_KEY │
│ GEMINI_API_KEY │
╰─────────────┬─────────────╯
│ read by
▼
╭───────────────────────────╮
│ ReqLLM │
│ per-call provider auth │
╰───────────────────────────╯Three concepts cover the config story:
- Four
:jidokakeys.default_model,default_generation,default_max_model_turns, anddefault_turn_timeout_ms. Each one has a built-in fallback insideJidoka.Config, so the application config block is optional for development. - Provider env vars. Jidoka never reads provider keys; ReqLLM does, at
call time. Setting
OPENAI_API_KEY(or the equivalent for another provider) is enough. - No dotenv loading. The package does not load
.envfiles. Set environment variables through your shell, your supervisor, or your deployment platform.
Security / Trust Boundaries
- Provider credentials must not appear in
config/*.exs. Compiled config is baked into releases; rotating a secret would force a redeploy and bake the old secret into release artifacts. - Per-agent credentials, tenant ids, and actor data belong in the runtime
context for a turn (
Jidoka.turn(spec, input, context: %{...})), not in the application config. Jidoka.Config.default_model/0resolves the configured model throughReqLLM.model/1. That call validates the model id but does not contact a provider; configuration is still side-effect free.- The four
:jidokakeys are public defaults. Treat them as the floor of agent behaviour: any agent may raise the loop budget or timeout, but no agent should silently lower the floor by relying on missing config. mix releasesnapshots application config at build time. Useconfig/runtime.exsfor any value that should be evaluated at boot, and read provider env vars throughSystem.fetch_env!/1if you must surface them at boot rather than at call time.
How To
Step 1: Set The Default Model
The model is the value most callers want to override. The string form is parsed by ReqLLM at first use.
# config/config.exs
import Config
config :jidoka, default_model: "openai:gpt-4o-mini"An agent that does not specify model "..." inherits this value. To pin a
specific agent, declare it in the DSL:
agent :time_agent do
model "anthropic:claude-3-5-sonnet"
endStep 2: Set Generation Defaults
Generation parameters control sampling. The default favours determinism for tests; relax it for product code that wants creative output.
config :jidoka,
default_generation: %{
params: %{
temperature: 0.7,
max_tokens: 1_024
}
}Jidoka.Config.default_generation/0 normalizes the value through
Jidoka.Agent.Spec.Generation.from_input/1 and raises with a useful error if
the map is malformed.
Step 3: Tune The Loop And Timeout Budget
Two integer keys cap a single turn's work.
config :jidoka,
default_max_model_turns: 6,
default_turn_timeout_ms: 20_000default_max_model_turns is the maximum number of model invocations inside
one tool loop; default_turn_timeout_ms is the wall-clock cap for the turn.
Both round-trip through Jidoka.Config.normalize_positive_integer/2, which
rejects zero and negative values with a clear error.
Step 4: Layer Env-Specific Overrides
The standard config/{dev,test,prod}.exs layering applies to :jidoka like
any other application:
# config/dev.exs
import Config
config :jidoka, default_model: "openai:gpt-4o-mini"# config/test.exs
import Config
config :jidoka,
default_model: %{provider: :test, id: "model"},
default_generation: %{params: %{temperature: 0.0, max_tokens: 200}},
default_max_model_turns: 4,
default_turn_timeout_ms: 5_000# config/prod.exs
import Config
config :jidoka, default_model: "openai:gpt-4o-mini"The :test model lets the deterministic test path bypass any real provider
client.
Step 5: Evaluate Late-Bound Values At Runtime
config/runtime.exs runs after release start. Use it to source values from
the environment without baking them into the release artifact:
# config/runtime.exs
import Config
if model = System.get_env("JIDOKA_DEFAULT_MODEL") do
config :jidoka, default_model: model
end
if budget = System.get_env("JIDOKA_DEFAULT_MAX_TURNS") do
config :jidoka, default_max_model_turns: String.to_integer(budget)
endStep 6: Export Provider Credentials Where The Application Can See Them
Jidoka does not read .env files. ReqLLM reads OPENAI_API_KEY and similar
env vars at call time. In development, export them in the shell:
export OPENAI_API_KEY=...
export ANTHROPIC_API_KEY=...
In production, use the deployment platform's secret manager (systemd
EnvironmentFile, Fly secrets, AWS Parameter Store, Kubernetes secrets) so
that the BEAM process sees them at boot. Inside Livebook, prefer the LB_*
prefix and mirror with Jidoka.Kino.load_provider_env/1. See
Kino Notebooks.
Common Patterns
- Keep
config.exsminimal. The four:jidokakeys plus animport_config "#{config_env()}.exs"line is enough for most apps. - Pin a deterministic model in
config/test.exs.%{provider: :test, id: "model"}keeps tests fully reproducible. - Lower the loop budget in tests. A short
default_max_model_turnssurfaces runaway loops fast. - Treat provider env vars as out-of-band configuration. Document the
required vars in the host application's README; do not try to encode them
in
:jidokakeys.
What Does Not Belong In :jidoka Config
- Per-agent overrides. Use the DSL:
model "...",generation %{...},controls do max_turns ... end. - Provider credentials. Use the process environment.
- Per-tenant or per-actor values. Use the runtime context passed to
Jidoka.turn/3orJidoka.chat/3. - Operation source registrations (
ash_resources,mcp_endpoints). Those belong in the supervision tree (Jido.MCP.register_endpoint/1) or the agent module. - Live LLM endpoints, request retries, or rate limits. Those live in ReqLLM
config (
config :req_llm, ...) or in the host's own request pipeline.
Testing
The configuration helpers are pure functions over Application.get_env/3,
so they are easy to test in isolation:
defmodule MyApp.JidokaConfigTest do
use ExUnit.Case, async: false
setup do
previous_model = Application.get_env(:jidoka, :default_model)
on_exit(fn ->
if previous_model do
Application.put_env(:jidoka, :default_model, previous_model)
else
Application.delete_env(:jidoka, :default_model)
end
end)
:ok
end
test "model defaults are normalized through ReqLLM" do
Application.put_env(:jidoka, :default_model, "openai:gpt-4o-mini")
assert Jidoka.Config.model_ref(Jidoka.Config.default_model()) == "openai:gpt-4o-mini"
end
test "invalid positive integer raises" do
assert_raise ArgumentError, ~r/invalid default_max_model_turns/, fn ->
Jidoka.Config.normalize_positive_integer!(0, :default_max_model_turns)
end
end
endAvoid async: true for tests that mutate Application env. The setup above
also captures and restores the previous value so the suite does not leak
state.
Troubleshooting
| Symptom | Likely Cause | Fix |
|---|---|---|
ArgumentError: invalid default_model: ... | The configured model string is not parseable by ReqLLM. | Use a provider:id string or a %{provider:, id:} map. |
ArgumentError: invalid default_max_model_turns: ... | The value is zero, negative, or not an integer. | Use a positive integer; strings are parsed when they trim to one. |
{:error, :missing_provider_credentials} from a live turn | The provider env var is not set in the BEAM process. | Export the var before starting the application or set it through your deployment platform. |
| Config changes do not take effect after deploy | config/config.exs is compiled into the release. | Move late-bound values to config/runtime.exs. |
Tests interfere with each other on :jidoka config | A test mutated Application.put_env/3 without an on_exit restore. | Capture the previous value in setup and restore it on exit. |
Reference
Key modules touched in this guide:
Jidoka.Config- typed accessors fordefault_model/0,default_generation/0,default_max_model_turns/0,default_turn_timeout_ms/0, and thenormalize_*helpers.Jidoka.Agent.Spec.Generation- shape of the generation map normalized fromdefault_generation.Jidoka- the facade that reads defaults when a turn does not override them.
Related Guides
- Getting Started - the smallest DSL agent end to end.
- Agent DSL - per-agent overrides for the four defaults.
- Errors And Config Reference - the full list of error structs and config keys.
- Jido Process Integration - supervising
Jidoka agents alongside the default
Jidoka.Jidoruntime. - Kino Notebooks - mirroring
LB_*secrets into provider env vars for Livebook.