Framework adapters for Forge — drop-in wrappers for LangGraph, CrewAI, AutoGen, and any async callable.
Project description
forge-adapters
Framework adapters for Forge.
Drop-in wrappers for LangGraph, CrewAI, AutoGen, and generic Python callables, all normalized into the same Forge runtime contract.
Why forge-adapters
Every agent framework brings its own execution model, callback system, and topology representation.
That becomes a problem the moment you want one operational layer across all of them:
- one orchestrator
- one task envelope
- one result type
- one event model
- one tracing and cost path
forge-adapters is the compatibility layer that makes that possible. It converts framework-specific flows into Forge's shared Adapter contract so the rest of the stack can stay uniform.
What ships in this package
LangGraphAdapterCrewAIAdapterAutoGenAdapterGenericCallableAdapterBaseAdapter- framework discovery helpers
- LangChain callback integration for LangGraph and CrewAI
Installation
Inside the Forge workspace:
uv sync
Standalone:
pip install forge-adapters
Framework-specific extras:
pip install 'forge-adapters[langgraph]'
pip install 'forge-adapters[crewai]'
pip install 'forge-adapters[autogen]'
pip install 'forge-adapters[all]'
Requirements:
- Python 3.11+
forge-core==0.1.0
The adapter contract
Every adapter in this package targets the same shape:
TaskEnvelope -> Adapter.run(...) -> RunResult
That means the orchestrator can load and run very different frameworks without changing the outer runtime model.
In practice, each adapter is responsible for:
- detecting or loading a user flow
- extracting a topology when possible
- executing the framework-specific runtime
- emitting or surfacing
RunEventdata - cooperating with the shared Forge interceptor and event bus
Supported adapters
LangGraphAdapter
Wraps compiled LangGraph graphs and injects Forge's LangChain callback into runtime config so model calls are observed through the shared interceptor.
What it does:
- detects
langgraphimports in Python source - loads a graph from a
graphvariable,build_graph()function, or a graph-like object in module scope - extracts graph nodes into
AgentCardtopology entries - instruments
ainvoke()orinvoke()execution paths - supports streaming through
astream_events()orastream()
This is the most direct path when a user already has a LangGraph workflow and wants Forge-level observability without rewriting the flow.
CrewAIAdapter
Wraps CrewAI crews and instruments execution through scoped monkey-patching plus LangChain callback injection.
What it does:
- detects
crewaiimports - loads a crew from a
crewvariable orbuild_crew()function - extracts agents, roles, descriptions, and model names into topology
- monkey-patches
Agent.execute_taskto emit agent-boundary events - monkey-patches
BaseTool._runto emit tool events - injects the shared LangChain callback into
Agent.llm.callbacks - runs
crew.kickoff()in a worker thread so the async runtime stays responsive
This adapter is designed for end-to-end observability without requiring changes inside the CrewAI flow itself.
AutoGenAdapter
Wraps AutoGen agent teams and instruments them through structured log handling.
What it does:
- detects
autogenandautogen_agentchatimports - loads a team from a
teamvariable orbuild_team()function - extracts participant topology when available
- attaches a temporary handler to AutoGen's structured trace logger
- converts AutoGen lifecycle and LLM log events into Forge events
- computes cost locally for LLM events before publishing them to the bus
This adapter is intentionally defensive around event payload drift, because structured logging schemas can move across framework versions.
GenericCallableAdapter
Wraps any async or sync callable into the Forge adapter interface.
This is the escape hatch for custom flows that do not live inside LangGraph, CrewAI, or AutoGen.
What it does:
- accepts any Python callable
- emits top-level
AGENT_STARTandAGENT_ENDboundaries - supports async callables directly
- supports sync callables via
asyncio.to_thread - scopes SDK monkey-patching for supported LLM clients during execution
That last point is the key differentiator. When the user calls SDKs directly inside their function, Forge can still capture telemetry through temporary instrumentation of common client libraries.
Framework discovery
forge_adapters.discovery provides file-based auto-detection for known frameworks.
Current signatures:
langgraphcrewaiautogenautogen_agentchat
Example:
from forge_adapters.discovery import discover_adapter
adapter = discover_adapter("my_flow.py")
This is the mechanism higher-level Forge components use to turn a Python file into the right adapter automatically.
Quickstart
Wrap a generic callable
import asyncio
from forge_adapters.generic import GenericCallableAdapter
from forge_core.types import TaskEnvelope
async def flow(payload: dict) -> dict:
return {"answer": f"hello {payload['name']}"}
async def main() -> None:
adapter = GenericCallableAdapter(fn=flow, adapter_name="hello_flow")
await adapter.load("<inline>")
result = await adapter.run(TaskEnvelope(input={"name": "forge"}))
print(result.output)
asyncio.run(main())
Detect a framework from source
from forge_adapters.discovery import discover_adapter
adapter = discover_adapter("my_langgraph_flow.py")
await adapter.load("my_langgraph_flow.py")
Shared execution model
All concrete adapters build on BaseAdapter, which provides:
- load lifecycle
- error handling
- run timing
RunResultconstruction- topology access
- default stream behavior
Framework-specific adapters override:
detect(...)_load_impl(...)_execute(...)
This keeps the package consistent without forcing every integration to reinvent the same boilerplate.
Instrumentation strategy by framework
One of the most important aspects of forge-adapters is that instrumentation is not uniform across frameworks, because the frameworks themselves are not uniform.
LangGraph
Uses callback injection.
- installs
ForgeLangChainCallback - routes model lifecycle into the shared interceptor
- lets the orchestrator aggregate costs from bus events
CrewAI
Uses monkey-patching plus callback injection.
- patches agent execution boundaries
- patches tool execution boundaries
- injects callbacks into
Agent.llm
AutoGen
Uses structured log consumption.
- listens to AutoGen's trace logger
- reconstructs LLM and agent events from
LogRecord.event - publishes populated Forge events onto the bus
Generic callable
Uses SDK monkey-patching.
- patches supported LLM SDK entrypoints inside a scoped context
- restores original methods after the run
- works for both async and sync user functions
This split is important because it shows the design is framework-aware rather than pretending every ecosystem can be instrumented the same way.
SDK patching in the generic adapter
The generic adapter is especially useful for direct SDK users because it scopes monkey-patching during the run and restores the original SDK methods afterward.
That gives you a path from:
plain Python function calling model SDKs directly
to:
Forge-compatible run with LLM_CALL events, token counts, and costs
without forcing the user to refactor their code into a specific framework.
Topology extraction
When possible, adapters convert framework-native structures into AgentCard entries.
Examples:
- LangGraph nodes become graph-node agents
- CrewAI agents surface role, goal, backstory, and model
- AutoGen participants become team agents
- Generic callable adapters expose a single synthetic node representing the wrapped flow
This gives dashboards and mutation systems a framework-independent topology view.
Public API at a glance
Top-level exports from forge_adapters:
BaseAdapterGenericCallableAdapterdiscover_adapter
Primary modules:
forge_adapters.baseforge_adapters.discoveryforge_adapters.genericforge_adapters.langgraph_adapterforge_adapters.crewai_adapterforge_adapters.autogen_adapterforge_adapters.langchain_callback
Package boundaries
forge-adapters focuses on framework integration only.
Related packages:
forge-core- protocols, types, orchestrator, event model
forge-observe- interceptor, tracer, metrics, cost model
forge-memory- memory backends and context injection
forge-cli- user-facing commands and package composition
This separation keeps adapter code focused on translating framework behavior rather than owning the entire runtime.
Recommended usage pattern
In a full Forge application, adapters are usually not used standalone. The typical flow is:
MetaOrchestratordetects or receives an adapter- The orchestrator wires the shared interceptor and bus into that adapter
- The adapter executes the framework-specific flow
- Costs, spans, and events flow back through the shared Forge runtime
That design is what makes framework diversity manageable without fragmenting observability or orchestration logic.
Testing
From the repository root:
pytest packages/forge-adapters/tests -q
The test suite covers:
- generic callable wrapping
- SDK monkey-patching and restoration
- CrewAI agent and tool instrumentation
- AutoGen structured-log instrumentation
- framework detection paths
- topology extraction behavior
- degraded execution when optional wiring is absent
License
Apache-2.0
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file forge_adapters-0.2.0-py3-none-any.whl.
File metadata
- Download URL: forge_adapters-0.2.0-py3-none-any.whl
- Upload date:
- Size: 33.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6f70c8ca06713005dab9a8ac6218a9aeccf3f0acf8723e45d926ddfd34b95d41
|
|
| MD5 |
9a253f397be3a0b64c07e6e5e1c5847f
|
|
| BLAKE2b-256 |
5d6d1bad7c91534364061f63b0d9b77cd17377cea79126811037d14166d51c22
|