The engine ships adapters for LangGraph and Google ADK. If you run a different framework (CrewAI, LlamaIndex, AutoGen, or your own runtime), you can wrap it as an Idun adapter by subclassingDocumentation 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.
BaseAgent. This page covers the abstract surface, the lifecycle the engine expects, and the limits of the extension point today.
The adapter factory in
idun_agent_engine.core.config_builder.ConfigBuilder.initialize_agent_from_config is currently a hardcoded if/elif over the AgentFramework enum. Wiring a new adapter therefore requires a small upstream change: either a fork or a PR. There is no Python entry-point hook today. This is on the roadmap; please open an issue if you need a stable plugin API.The base class
BaseAgent lives in libs/idun_agent_engine/src/idun_agent_engine/agent/base.py. It is an ABC with the following surface:
Required overrides
| Member | Kind | What you return |
|---|---|---|
id | property | A stable string identifier for this adapter instance |
agent_type | property | A short label (e.g. "LangGraph", "ADK", "CrewAI") |
agent_instance | property | The underlying framework’s compiled agent object |
copilotkit_agent_instance | property | A CopilotKit-compatible wrapper, or the same instance if not applicable |
infos | property | A diagnostic dict surfaced via /_engine/info |
initialize(config, observability=None) | async method | Parse config, instantiate the framework agent, wire observability |
invoke(message) | async method | One-shot non-streaming run (used by the deprecated /agent/invoke route) |
stream(message) | async generator | Pre-AG-UI stream (used by the deprecated /agent/stream route) |
run(input_data) | async generator | Canonical AG-UI entry point. Accepts RunAgentInput, yields BaseEvent |
discover_capabilities() | method | Return AgentCapabilities describing input/output schemas |
run is the only path the modern POST /agent/run route uses. invoke and stream exist for the deprecated /agent/invoke and /agent/stream compatibility shims. New adapters should focus on run; invoke and stream can raise NotImplementedError if you do not need the deprecated routes.Optional overrides
| Member | Default behaviour |
|---|---|
history_capabilities() | Returns HistoryCapabilities(can_list=False, can_get=False) |
list_sessions(user_id=None) | Raises NotImplementedError. Override to expose session history. |
get_session(session_id, user_id=None) | Raises NotImplementedError. Override to fetch a single session. |
get_graph_ir() | Raises NotImplementedError. Override to enable the admin panel’s live graph visualisation. |
draw_mermaid() | Renders get_graph_ir() as Mermaid. Override only if you have a faster path. |
draw_ascii() | Renders get_graph_ir() as ASCII. Same. |
Constructor
Your__init__ must call super().__init__() to populate self.run_event_observers: RunEventObserverRegistry. Run-event observers are how the standalone trace pipeline subscribes to AG-UI events for the local trace store.
Minimal adapter sketch
my_adapter.py
Lifecycle
- Boot. The engine reads
config.yaml, validates theagent.typefield against theAgentFrameworkenum, and instantiates your adapter class. initialize(config, observability). Called once. Use this to parseagent.config, instantiate your framework, and register callbacks. Raise an exception to abort boot.discover_capabilities(). Called by the engine to populate/agent/capabilities. The standalone admin UI uses the result to choose between the chat input and the structured-JSON input.run_event_observersregistration. The engine subscribes its trace pipeline before serving the first request. Yourrun()method does not need to know about observers:BaseAgenthandles dispatch when AG-UI events are yielded.run(input_data). Called per request toPOST /agent/run. The HTTP layer iterates the generator and forwards each event over Server-Sent Events. The deprecated/agent/invokeand/agent/streamroutes delegate toinvoke()andstream()respectively.
Capability discovery
AgentCapabilities describes what your adapter accepts and returns. The standalone UI uses this to render the right input control.
InputDescriptor.mode is Literal["chat", "structured"]. OutputDescriptor.mode is Literal["text", "structured", "unknown"]. When input.mode == "structured", the standalone chat surface validates that messages[-1].content is JSON matching the schema before forwarding to your adapter.
Wiring the adapter into the engine
Until a plugin API ships, you need to register your adapter in two places.1. Use or add an enum value
TheAgentFramework enum in idun_agent_schema/engine/agent_framework.py already ships a CUSTOM slot that you can claim without forking the schema. If you need a named slot for upstream contribution, add one:
2. Add a branch in ConfigBuilder.initialize_agent_from_config
config.yaml:
Reference adapter: LangGraph
The LangGraph adapter atlibs/idun_agent_engine/src/idun_agent_engine/agent/langgraph/langgraph.py is the most complete worked example. Reading it end-to-end is the fastest way to see how:
_load_graph_builderresolves thegraph_definitionstring (file path first, module fallback)_setup_persistenceconfiguresInMemorySaver,AsyncSqliteSaver, orAsyncPostgresSaverbased on the checkpointer configdiscover_capabilities()readsgraph.input_schemaandgraph.output_schemato detect chat vs structured moderun()delegates to LangGraph’s AG-UI wrapper (LangGraphAGUIAgent) which emitsRunStarted,StepStarted,TextMessageStart/Content/End,ToolCallStart/Args/End,ThinkingStart/End, andRunFinishedeventsget_graph_ir()introspects the compiled graph and emits a framework-agnosticAgentGraphfor the admin panel
What’s next
Custom observability handler
The same extension pattern for tracing providers.
SSO
JWT validation works for any adapter.
Troubleshooting
Common boot failures.