# Base llm_core configuration
[routing]
default = "claude"
[routing.tasks.coding]
alias = "openai"
mode = "passthrough"
capabilities = { structured_output = true, tool_use = true }
[routing.tasks.planning]
alias = "claude"
mode = "abstracted"
capabilities = { reasoning = true }
[memory.hindsight]
enabled = true
default_bank_id = "${HINDSIGHT_DEFAULT_BANK}"
url = "${HINDSIGHT_URL}"
timeout_recall_ms = 4000
timeout_reflect_ms = 5000
[telemetry]
log_pipeline_events = true
log_provider_dispatch = true
sample_rate = 1.0
enable_logger = true
logger_level = "info"
[providers.anthropic]
module = "LlmCore.LLM.Anthropic"
type = "cloud"
enabled = true
default_model = "claude-3-5-sonnet"
aliases = ["anthropic", "claude"]
cost_tier = "premium"
[providers.anthropic.agent]
name = "claude"
config = {model = "claude-3-5-sonnet", temperature = 0.2}
[providers.anthropic.auth]
api_key_env = "ANTHROPIC_API_KEY"
[providers.anthropic.capabilities]
structured_output = true
tool_use = true
vision = true
streaming = true
[providers.openai]
module = "LlmCore.LLM.OpenAI"
type = "cloud"
enabled = true
default_model = "gpt-4o-mini"
aliases = ["openai", "gpt"]
cost_tier = "standard"
[providers.openai.agent]
name = "openai"
config = {model = "gpt-4o-mini", temperature = 0.1}
[providers.openai.auth]
api_key_env = "OPENAI_API_KEY"
[providers.openai.capabilities]
structured_output = true
tool_use = true
vision = true
streaming = true
[providers.ollama]
module = "LlmCore.LLM.Ollama"
type = "local"
enabled = true
default_model = "llama3.1"
aliases = ["ollama", "local"]
cost_tier = "local"
[providers.ollama.agent]
name = "ollama"
config = {model = "llama3.1", temperature = 0.7}
[providers.ollama.options]
base_url = "${OLLAMA_URL:http://localhost:11434}"
[providers.ollama.capabilities]
structured_output = true
tool_use = false
vision = false
streaming = true
[providers.appliance]
module = "LlmCore.LLM.Appliance"
type = "local"
enabled = true
default_model = "qwen3.5-27b-claude-4.6-opus-distilled-mlx"
aliases = ["appliance", "local", "lmstudio"]
cost_tier = "free"
[providers.appliance.capabilities]
tool_use = true
streaming = true
[providers.zai]
module = "LlmCore.LLM.OpenAI"
type = "cloud"
enabled = true
default_model = "glm-5.1"
aliases = ["zai", "z"]
cost_tier = "plan"
[providers.zai.config]
base_url = "https://api.z.ai/api/coding/paas/v4"
[providers.zai.auth]
api_key_env = "ZAI_API_KEY"
[providers.zai.capabilities]
tool_use = true
streaming = true
# ── CLI Providers ─────────────────────────────────────────────
#
# CLI providers use type = "cli" and configure the CLI surface in
# [providers.<id>.cli]. No Elixir module needed — just config.
#
# To add a custom CLI provider, copy any block below and adjust.
# To override a default, redefine the same [providers.<id>] in a
# project or global override TOML.
[providers.claude_code]
type = "cli"
enabled = true
aliases = ["claude-code"]
[providers.claude_code.cli]
binary = "claude"
default_timeout = 1800000
model_resolution = "provider_runtime"
prompt_position = "flagged"
prompt_flag = "-p"
prompt_transport = "flagged"
system_prompt_transport = "file_flag"
add_dir_flag = "--add-dir"
output_mode = "stdout_text"
stdin_hack = true
prefix_args = ["--print"]
install_hint = "Install with: npm install -g @anthropic/claude-code"
[providers.claude_code.cli.flags]
model = "--model"
permission_mode = "--permission-mode"
dangerously_skip_permissions = "--dangerously-skip-permissions"
allow_dangerously_skip_permissions = "--allow-dangerously-skip-permissions"
allowed_tools = "--allowed-tools"
disallowed_tools = "--disallowed-tools"
system_prompt = "--append-system-prompt"
system_prompt_file = "--append-system-prompt-file"
add_dir = "--add-dir"
[providers.claude_code.cli.preflight]
help_args = ["--help"]
expect_in_help = ["--print", "--model"]
[providers.claude_code.capabilities]
streaming = true
passthrough = true
[providers.claude_code.metadata]
cost_tier = "cli"
# ──
[providers.droid]
type = "cli"
enabled = true
aliases = ["droid"]
[providers.droid.cli]
binary = "droid"
subcommand = "exec"
default_timeout = 1800000
default_model = "claude-opus-4-6"
model_resolution = "gc_default"
prompt_position = "last"
prompt_transport = "last"
system_prompt_transport = "file_flag"
cwd_flag = "--cwd"
output_mode = "stdout_text"
stdin_hack = false
auto_approve_args = ["--auto", "high"]
install_hint = "Install with: curl -fsSL https://app.factory.ai/cli | sh"
[providers.droid.cli.flags]
model = "--model"
auto = "--auto"
cwd = "--cwd"
worktree = "--worktree"
system_prompt = "--append-system-prompt"
system_prompt_file = "--append-system-prompt-file"
enabled_tools = "--enabled-tools"
disabled_tools = "--disabled-tools"
[providers.droid.cli.preflight]
help_args = ["exec", "--help"]
expect_in_help = ["--auto", "--cwd"]
[providers.droid.capabilities]
streaming = true
passthrough = true
[providers.droid.metadata]
cost_tier = "cli"
# ──
[providers.pi_cli]
type = "cli"
enabled = true
aliases = ["pi", "pi-cli"]
[providers.pi_cli.cli]
binary = "pi"
default_timeout = 1800000
model_resolution = "provider_runtime"
prompt_position = "last"
prompt_transport = "last"
system_prompt_transport = "file_flag"
output_mode = "stdout_text"
stdin_hack = true
# --no-session --no-extensions: prevent extension auto-loading in
# daemon-dispatched runs where duplicate tool registrations can cause
# Pi startup conflicts and apparent dispatch timeouts.
prefix_args = ["--print", "--no-session", "--no-extensions"]
install_hint = "Install pi CLI and ensure `pi` is in PATH"
[providers.pi_cli.cli.flags]
model = "--model"
provider = "--provider"
thinking = "--thinking"
system_prompt = "--append-system-prompt"
system_prompt_file = "--append-system-prompt"
[providers.pi_cli.cli.preflight]
help_args = ["--help"]
expect_in_help = ["--print", "--model"]
[providers.pi_cli.capabilities]
streaming = true
passthrough = true
[providers.pi_cli.metadata]
cost_tier = "cli"
# ──
[providers.kimi_cli]
type = "cli"
enabled = true
aliases = ["kimi", "kimi-cli"]
[providers.kimi_cli.cli]
binary = "kimi-cli"
default_timeout = 1800000
model_resolution = "provider_runtime"
prompt_position = "flagged"
prompt_flag = "--prompt"
prompt_transport = "flagged"
system_prompt_transport = "file_flag"
# Kimi's --agent-file expects a YAML agent spec, not raw markdown.
# This transform generates agent.yaml + sibling system.md from the
# caller's system prompt text. Values resolve as:
# dispatch opts > file_transform_defaults > built-in fallbacks
system_prompt_file_transform = "agent_spec_yaml"
cwd_flag = "--work-dir"
add_dir_flag = "--add-dir"
output_mode = "final_message_only"
stdin_hack = false
prefix_args = ["--print", "--output-format", "text", "--final-message-only"]
# Kimi appends a resumable session footer even in final-message mode.
# Strip it at the provider layer so downstream callers see only the final reply.
output_strip_patterns = ["\\n{2,}To resume this session: kimi -r [^\\n]+\\s*$"]
auto_approve_args = ["--yolo"]
install_hint = "Install Kimi CLI and ensure `kimi-cli` is in PATH"
[providers.kimi_cli.cli.flags]
model = "--model"
cwd = "--work-dir"
add_dir = "--add-dir"
system_prompt_file = "--agent-file"
[providers.kimi_cli.cli.preflight]
help_args = ["--help"]
expect_in_help = ["--agent-file", "--print", "--work-dir"]
[providers.kimi_cli.cli.file_transform_defaults]
version = 1
extend = "default"
[providers.kimi_cli.capabilities]
streaming = true
passthrough = true
[providers.kimi_cli.metadata]
cost_tier = "cli"
# ──
[providers.codex_cli]
type = "cli"
enabled = true
aliases = ["codex", "codex-cli"]
[providers.codex_cli.cli]
binary = "codex"
subcommand = "exec"
default_timeout = 1800000
model_resolution = "provider_runtime"
prompt_position = "last"
prompt_transport = "last"
system_prompt_transport = "inline_fallback"
cwd_flag = "--cd"
add_dir_flag = "--add-dir"
output_mode = "stdout_text"
stdin_hack = false
# Codex supports writing the final response to a file, bypassing
# stdout session noise (banners, progress indicators, etc.)
output_file_flag = "--output-last-message"
auto_approve_args = ["--full-auto"]
sandbox_bypass_args = ["--dangerously-bypass-approvals-and-sandbox"]
install_hint = "Install with: npm install -g @openai/codex"
[providers.codex_cli.cli.flags]
model = "--model"
cwd = "--cd"
add_dir = "--add-dir"
[providers.codex_cli.cli.preflight]
help_args = ["exec", "--help"]
expect_in_help = ["--full-auto", "--add-dir"]
[providers.codex_cli.capabilities]
streaming = true
passthrough = true
[providers.codex_cli.metadata]
cost_tier = "cli"
# ──
[providers.gemini_cli]
type = "cli"
enabled = true
aliases = ["gemini", "gemini-cli"]
[providers.gemini_cli.cli]
binary = "gemini"
default_timeout = 1800000
model_resolution = "provider_runtime"
prompt_position = "last"
prompt_transport = "last"
output_mode = "stdout_text"
stdin_hack = false
install_hint = "Install the Google Cloud CLI with Gemini support"
[providers.gemini_cli.cli.flags]
model = "--model"
[providers.gemini_cli.cli.preflight]
help_args = ["--help"]
[providers.gemini_cli.capabilities]
streaming = true
passthrough = true
[providers.gemini_cli.metadata]
cost_tier = "cli"
# ── Custom CLI Provider Example ──────────────────────────────
#
# [providers.my_tool]
# type = "cli"
# enabled = true
# aliases = ["my-tool", "mt"]
#
# [providers.my_tool.cli]
# binary = "my-tool"
# default_model = "v2"
# default_timeout = 60000
# prompt_position = "last"
# stdin_hack = false
# install_hint = "pip install my-tool"
# prefix_args = ["--no-interactive"]
# auto_approve_args = ["--yes"]
#
# [providers.my_tool.cli.flags]
# model = "--model"
# temperature = "--temp"
#
# [providers.my_tool.cli.preflight]
# help_args = ["--help"]
# expect_in_help = ["--model"]
#
# [providers.my_tool.capabilities]
# streaming = true
# passthrough = true
#
# [providers.my_tool.metadata]
# cost_tier = "cli"
# ── Native Provider Cascade ──────────────────────────────────
#
# The ordered list of providers tried when dispatching an in-process
# agentic loop. First available wins.
#
# Change this when subscriptions change, local hardware changes,
# or you want to prioritize a different provider.
[native]
cascade = ["appliance", "zai", "anthropic"]
[native.default_models]
appliance = "qwen3.5-27b-claude-4.6-opus-distilled-mlx"
zai = "glm-5.1"
anthropic = "claude-sonnet-4-6"
# When a model name contains these substrings, route to the named provider.
# Evaluated in order; first match wins. Applies when model is specified
# but not found on the appliance.
[[native.model_routing]]
pattern = "claude"
provider = "anthropic"
[[native.model_routing]]
pattern = "glm"
provider = "zai"
[[native.model_routing]]
pattern = "zai"
provider = "zai"
[[native.model_routing]]
pattern = "gpt"
provider = "openai"
[[native.model_routing]]
pattern = "openai"
provider = "openai"