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 |
Related Documentation¶
- Concepts — the rules connectors implement
- Observability and Audit — spans and reports produced during a turn
- API Reference — the
connectorspages
Last Updated: October 2026 Status: Implemented