Skip to main content

Getting Started

The shortest path from a fresh install to a chat reply is roughly two minutes. You write a YAML, the daemon compiles it, and you talk to it from the terminal.

You'll need Digitorn itself (download from the releases page or build from source), and a way for the agent to call an LLM. That last part can be a cloud API key (DeepSeek, OpenAI, Anthropic, Groq...) or a local model server such as Ollama, LM Studio, or vLLM. The example below picks the local route, so a running Ollama is enough.

Your first app​

Save the following as hello.yaml. The brain block points at a local Ollama model so nothing leaves the machine; if you'd rather use a cloud provider, the providers section further down has drop-in replacements.

app.yaml
app:
app_id: hello
name: "Hello App"
description: "My first Digitorn app"

runtime:
mode: conversation

agents:
- id: assistant
role: assistant
brain:
provider: ollama
model: qwen25-7b-gpu:latest
backend: openai_compat
config:
base_url: http://localhost:11434/v1
api_key: ollama
system_prompt: |
You are a friendly assistant. Answer questions concisely.

tools:
modules:
memory: {}
capabilities:
default_policy: auto
grant:
- module: memory
actions: [remember]

ui:
greeting: "Hello! I'm your assistant. Ask me anything."

If you'd rather use a cloud provider, drop in one of the brain blocks from Using different providers and export the matching API key.

Running the app​

digitorn install compiles, validates and installs apps.
digitorn install hello.yaml pushes the YAML through compiler and reports errors before any bootstrap happens. A green checkmark means the app definition is structurally sound; runtime issues (a service that's down, a file that isn't where you expected) can still happen, but the YAML itself is correct. install also deploys the app and arms any background channel providers the YAML declares.

To talk to the app from the terminal:

bash
digitorn chat hello

chat is interactive - type your message once the TUI opens. If a tool call needs approval (tools.capabilities.approve), the TUI shows an approval widget ([y/a] approve / deny) rather than blocking silently, so it's still the simplest way to test a deployed app end-to-end.

What validation checks​

Compile-time validation is fairly thorough, which is why so many classes of bug never reach runtime. The YAML must parse as a mapping at the root, then every block is validated with unknown keys rejected, so types, required fields, literal sets, and value ranges are all enforced. Each {{...}} reference has to resolve, and a missing {{env.X}} is a compile error (use the ?? fallback operator if you want an optional value).

The compiler also checks identifiers against the catalog: brain.backend must be one of the known backends (a typo produces a "did you mean" suggestion) - brain.provider itself is a free-form string, not catalog-checked, so a typo there compiles clean and just means the wrong provider at runtime; every key under tools.modules must match a registered module; every setup[].action must exist on its module, with its params validated against the action's param schema. Capabilities (tools.capabilities.grant, approve, deny, hidden_actions) and the agents[].modules shape are checked the same way.

When digitorn install returns clean, the structural part is done.

How it works​

Inside one turn, the system prompt and the user input are sent to the LLM. The LLM replies with text, tool calls, or both. Each tool call is routed through the context builder (context_builder.execute_tool); the result streams back into the next iteration. The loop ends when the LLM stops emitting tool calls, or when runtime.max_turns is hit, whichever comes first.

Execution modes​

The same agent loop drives three usable runtime.mode settings. The default is conversation, which is what hello.yaml uses: an interactive multi-turn chat. one_shot reads a single input from runtime.input, runs the agent once, and returns it through runtime.output. background hands control to the daemon, which wakes the agent on cron schedules, HTTP webhooks, RSS feeds, and the rest of the channel providers documented in Channels. The one_shot input/output contract is detailed in App Configuration → runtime.

A fourth value, pipeline, exists in the schema but the compiler rejects it outright (mode: pipeline is not executed by the daemon) - to chain apps together, use a flow: graph or call_app instead. See Composition.

Using different providers​

The brain block is the only thing that changes when you swap providers; everything else in the YAML stays put. The cloud providers all read their key from an environment variable through the {{env.X}} template, except the Claude Code alias which delegates to ~/.claude/.credentials.json.

yaml
# DeepSeek
brain:
provider: deepseek
model: deepseek-chat
backend: openai_compat
config:
api_key: "{{env.DEEPSEEK_API_KEY}}"

# OpenAI
brain:
provider: openai
model: gpt-4o
backend: openai_compat
config:
api_key: "{{env.OPENAI_API_KEY}}"

# Anthropic (native backend)
brain:
provider: anthropic
model: claude-sonnet-4-5
backend: anthropic
config:
api_key: "{{env.ANTHROPIC_API_KEY}}"

# Anthropic via Claude Code OAuth
brain:
provider: anthropic
model: claude-sonnet-4-5
backend: anthropic
config:
api_key: "claude-code" # alias - reads ~/.claude/.credentials.json

# Groq (fast inference)
brain:
provider: groq
model: llama-3.3-70b-versatile
backend: openai_compat
config:
api_key: "{{env.GROQ_API_KEY}}"
base_url: "https://api.groq.com/openai/v1"

provider is a free-form label, not validated against a catalog - see Agents → Brain for exactly what is and isn't checked at compile time.

For local model servers, the shape is the same; you point base_url at the local endpoint and skip the API key.

yaml
brain:
provider: ollama
model: qwen2.5:14b-instruct-q4_K_M
backend: openai_compat
config:
base_url: "http://localhost:11434/v1"
context:
max_tokens: 8000
strategy: truncate
keep_recent: 6

Tool schemas always go out through the API's native tools= parameter, whatever the backend - there's no separate mode to turn on for local models. Small or older local models sometimes answer with a tool call shaped as plain text anyway even though they got the real schema; when that happens a format-recovery parser tries to salvage a call out of the text before giving up - see Tools → When a model answers in plain text instead of calling a tool.

Useful CLI commands​

The commands you'll actually use early on:

bash
digitorn install <app.yaml>                  # install an app
digitorn list # list installed apps
digitorn uninstall <app-id> # remove an app

digitorn chat <app-id> # interactive TUI chat
digitorn sessions <app-id> # list recent sessions

Next steps​

Once hello.yaml is running, the natural next page is App Configuration for the full reference of the YAML surface. From there, Agents covers brain fallback and multi-agent setups, Tools explains how tool schemas reach the LLM, and Context Management goes into compaction and token budgeting. Examples has end-to-end real apps if you'd rather learn by reading whole YAMLs.