Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.idun-group.com/llms.txt

Use this file to discover all available pages before exploring further.

You already have an agent. Maybe it’s a LangGraph StateGraph in my_agent.py, or an ADK Agent in a Python package. This guide shows the smallest possible step from “I have an agent” to “I have an HTTP service with a chat UI, traces, and admin panel.”

Prerequisites

  • Python 3.12 or newer
  • Your agent code, with a top-level variable that holds the graph (LangGraph) or agent (ADK)
  • pip install idun-agent-engine (this ships the idun CLI and the bundled standalone admin UI)

Example: a LangGraph echo agent

Assume you have my_agent.py in the current directory:
my_agent.py
from typing import TypedDict
from langgraph.graph import StateGraph, START, END


class State(TypedDict):
    messages: list


def echo(state: State) -> dict:
    last = state["messages"][-1]
    text = last.content if hasattr(last, "content") else str(last)
    return {"messages": state["messages"] + [{"role": "assistant", "content": text}]}


builder = StateGraph(State)
builder.add_node("echo", echo)
builder.add_edge(START, "echo")
builder.add_edge("echo", END)

graph = builder  # <-- this is what Idun will load
Assign an uncompiled StateGraph to the top-level variable. The engine compiles it with its own checkpointer and store. A CompiledStateGraph is also accepted (the engine extracts its .builder and recompiles), but you’ll see a deprecation warning.

Step 1: Write a minimal config.yaml

config.yaml
server:
  api:
    port: 8000

agent:
  type: "LANGGRAPH"
  config:
    name: "My agent"
    graph_definition: "./my_agent.py:graph"
Three fields do all the work:
  • agent.type: "LANGGRAPH" or "ADK" (case-insensitive). Determines which adapter wraps your code.
  • agent.config.name: display name shown in the admin panel.
  • agent.config.graph_definition: "<path>:<variable>" for LangGraph. For ADK, the equivalent field is agent.config.agent.

graph_definition format

The string is parsed as <path_or_module>:<variable_name>. The engine tries file-path resolution first, then falls back to Python module import:
# File path (relative or absolute)
graph_definition: "./my_agent.py:graph"
graph_definition: "src/agents/router.py:app"

# Python module path (when your package is importable)
graph_definition: "my_package.agents.router:graph"
Common variable names: graph, app, agent. Anything that resolves to a StateGraph works.

Step 2: Run

For evaluation and local development, use the standalone launcher:
idun init
idun init runs Alembic migrations, seeds the DB from your config.yaml, opens your browser, and serves on http://localhost:8000.

Skipping Step 1: let the wizard find your agent

If you’d rather not hand-write config.yaml, idun init ships with an onboarding scanner that walks the current folder and offers any LangGraph or Google ADK agents it finds. Drop into an existing repo, run idun init, and the wizard surfaces the detected agents so you can pick one without touching YAML. The scanner (libs/idun_agent_standalone/src/idun_agent_standalone/services/scanner.py) looks at three sources, in order of confidence:
SourceConfidenceWhat it parses
config.yaml or config.yml at depth 0 to 2HIGHReads agent.type and either graph_definition (LangGraph) or agent (ADK).
langgraph.json at the rootHIGHOne detection per entry in the graphs dict.
.py source files, depth up to 4MEDIUMRegex pre-filter for langgraph, deepagents, or google.adk imports, then AST analysis.
From Python source, the AST pass recognizes:
  • StateGraph(...) and <g>.compile() where <g> is a known StateGraph binding
  • Factory calls: create_react_agent (from langgraph.prebuilt) and create_deep_agent (from deepagents)
  • Same-module builder functions that return a LangGraph (the common graph = _build() idiom)
  • ADK agent classes: Agent, LlmAgent, SequentialAgent, ParallelAgent, LoopAgent
A few limits worth knowing:
  • The walker stops at depth 4 and skips standard junk directories (.git, __pycache__, node_modules, .venv, venv, env, dist, build, target, plus any dot-folder).
  • Files over 1 MB are skipped to keep the scan fast.
  • Symlinks are not followed.
  • Parse errors (broken YAML, syntax errors in a .py file) are silently skipped; the scan never fails on malformed input.
When multiple sources point at the same (file_path, variable_name), the highest-confidence detection wins, so a YAML or langgraph.json entry always beats a source-only match for the same target. The wizard then runs a 6-rule cascade to pick a display name: config.name, then the langgraph.json graph key, then pyproject.toml’s project.name, then the parent directory (skipping src), then the filename with a trailing _agent stripped, and finally My Agent as a fallback. Subsequent boots only need:
idun serve
By default, IDUN_CONFIG_PATH points at ./config.yaml. Override with --config or the env var if your config lives elsewhere:
idun setup --config ./prod/config.yaml
idun serve

Or run programmatically (engine-only)

If you don’t want the admin panel and DB-backed config, use the engine SDK directly. No CLI, no DB, no UI:
serve.py
from idun_agent_engine import run_server_from_config

run_server_from_config("config.yaml")
python serve.py
The engine reads the YAML, instantiates your graph, and serves the AG-UI streaming endpoint at POST /agent/run. You bring your own admin tooling.

Step 3: Test the agent

Open http://localhost:8000/ in a browser. The chat UI streams your agent’s responses. Or call the API directly:
curl -X POST http://localhost:8000/agent/run \
  -H "Content-Type: application/json" \
  -d '{
    "thread_id": "test-1",
    "messages": [{"role": "user", "content": "Hello"}]
  }'
You’ll receive a server-sent event stream of AG-UI events.

What you got for free

By writing eight lines of YAML, you now have:
  • A FastAPI service at /agent/run with AG-UI streaming
  • A chat UI at /
  • An admin panel at /admin/ for editing guardrails, memory, MCP servers, observability, and integrations
  • A trace viewer at /admin/traces/ with a waterfall span tree
  • An OpenAPI schema at /docs
To add guardrails, observability, MCP servers, or per-agent SSO, edit the YAML or use the admin panel: no agent code change required.

ADK agents

The flow is identical, with agent.type: "ADK" and the agent field instead of graph_definition:
config.yaml
server:
  api:
    port: 8000

agent:
  type: "ADK"
  config:
    name: "My ADK agent"
    agent: "./my_adk_agent.py:root_agent"
    session_service:
      type: "in_memory"
    memory_service:
      type: "in_memory"
See ADK frameworks reference for full configuration options.

What’s next

Production hardening

before exposing this beyond localhost

Guardrails overview

add input and output guards

Observability overview

wire Langfuse, Phoenix, or LangSmith

MCP Servers

attach MCP servers

Troubleshooting

graph load errors, reload failures
Last modified on May 22, 2026