Skip to content

Connectors

Overview

A connector builds an atom into a native agent of one framework and installs chatomon's checks as the outermost layer of that agent. The connectors implement the same engine rules and pass the shared contract test suite (tests/contract/); each framework has its own page for conversations, streaming and tracing.

Table of Contents

Document Description
PydanticAI PydanticAIConnector: the agent it builds, message history, streaming limits, tracing
LangChain / LangGraph LangChainConnector: the graph it builds, checkpointers, streaming, parent_span, human in the loop
Microsoft Agent Framework MAFConnector and MAFFoundryConnector: local sessions, Foundry, streaming limits
Google ADK ADKConnector: the app it builds, sessions, streaming, ADK's own telemetry, paused runs

What "Native" Means

Atom.build() returns the framework's own object, so you keep using the framework's API:

Connector build() returns Extra keyword arguments go to
PydanticAIConnector pydantic_ai.Agent with text output pydantic_ai.Agent
LangChainConnector LangGraph CompiledStateGraph from create_agent langchain.agents.create_agent
MAFConnector agent_framework.Agent agent_framework.Agent
MAFFoundryConnector agent_framework.foundry.FoundryAgent FoundryAgent
ADKConnector google.adk.apps.App with an LlmAgent as its root agent LlmAgent; app_kwargs goes to App

chatomon sets the prompt and name from the atom, so the arguments that would conflict are refused with ChatomonConfigError (listed on each framework's page). Your own capabilities or middleware run inside chatomon's layer; in ADK your plugins and callbacks run after chatomon's plugin.

How the Rules Map onto Each Framework

flowchart TB
    subgraph PydanticAI
        P1[before_model_request<br/>run input chain, redact blocked message] --> P2[wrap_model_request<br/>add guidance, canned reply, output chain, regenerations]
        P2 --> P3[wrap_run<br/>finish or abort the turn]
    end
    subgraph LangChain
        L1[before_agent<br/>run input chain, redact by message id, jump to end on reply] --> L2[wrap_model_call<br/>add guidance, output chain, regenerations]
        L2 --> L3[after_agent<br/>finish the turn, clear private state]
    end
    subgraph MAF
        M1[AgentMiddleware<br/>run input chain, redact blocked message] --> M2[ChatMiddleware<br/>guidance, final output checks, regenerations]
        M2 --> M3[local session history and turn report]
    end
    subgraph ADK
        A1[plugin on_user_message<br/>run input chain, replace blocked message] --> A2[plugin before_run<br/>end the run when an orbital replies]
        A2 --> A3[nucleus model<br/>add guidance, output chain, regenerations]
        A3 --> A4[plugin after_run<br/>finish or abort the turn]
    end

Output checks and regenerations happen around the model call, before approved replies enter conversation history. Guidance is added to the current model request and is not stored. PydanticAI, LangChain and Google ADK support both their native async and sync APIs; MAF exposes an async native API. Both MAF connectors support checked output on non-streaming runs.

At a Glance

PydanticAI LangChain MAF Google ADK
Where the history lives The message_history you pass to the next run The graph's checkpointer Local AgentSession history provider, with store=False The session of the runner's session service
Conversation id in reports The run's conversation_id The thread_id of the run config The local session_id The id of the ADK session
Streaming with output orbitals run_stream is refused Only the approved reply is streamed run(..., stream=True) is refused Each reply arrives whole, once approved
Span nesting Automatic Through parent_span Automatic Automatic

Tools

Tools are declared on the native agent as usual. Model responses that call tools are intermediate steps: output orbitals are not run on them and they do not end the turn. The output chain runs on the final text reply.

Judges and Model Resolution

A JudgeOrbital without its own connector calls its model through the atom's connector. PydanticAI, LangChain and Google ADK accept resolve_model; by default PydanticAI uses the ID as a model string, LangChain calls init_chat_model with it and ADK resolves it with its model registry. MAF needs a resolve_client callback because its core package does not resolve model IDs to chat clients.

Failures

If the model or the framework raises during a turn, the connector closes the turn with Engine.abort_turn — the report says aborted and records the exception type — and the exception propagates to your code. LangChain's tools and interrupt() are covered on its page; cancelled and paused ADK runs on the ADK page.

A turn whose nucleus ends with a reply that has no text is closed as aborted too. There is nothing to check, so the output orbitals do not run on it and the report has no attempt for it. LangChain, MAF and ADK raise nothing: your code receives the empty reply as the framework returned it, and the report records RuntimeError as the exception type. PydanticAI asks the model again and raises UnexpectedModelBehavior when its retries are over.

Key Components

Component Location Purpose
Connector src/chatomon/connectors/base.py The extension point every connector implements
PydanticAIConnector src/chatomon/connectors/pydantic_ai.py Builds atoms into PydanticAI agents
LangChainConnector src/chatomon/connectors/langchain.py Builds atoms into LangChain agents (LangGraph graphs)
MAFConnector, MAFFoundryConnector src/chatomon/connectors/maf/ Build atoms into MAF core and Foundry agents
ADKConnector src/chatomon/connectors/adk.py Builds atoms into Google ADK apps
Contract suite tests/contract/ The rules every connector must pass

Last Updated: October 2026 Status: Implemented