Weave

Interop: connect foreign-framework agents

This is why Weave exists: take an agent someone already built (in LangChain, LangGraph, CrewAI, or plain Python) and connect it to your agent without rewriting it.

A foreign agent is wrapped into a Weave BaseAgent. Because it becomes an agent, it composes in Pipeline, Parallel, and any nesting exactly like a native one, and the connection protocol auto-calibrates the handoff (type-checks, injects transforms).

Duck-typed, zero new dependencies. These bridges call the foreign object's documented entrypoint (a LangChain Runnable's ainvoke/invoke, a CrewAI crew's kickoff) rather than importing the framework. Weave's core stays dependency-free, and any object that speaks the interface plugs in, with no version pinning.

LangChain / LangGraph

from_langchain targets the Runnable protocol (ainvoke/invoke) that LangChain chains, chat models, agents, and compiled LangGraph graphs all implement.

from weave import from_langchain, Pipeline

# `chain` is any LangChain Runnable / LangGraph graph you already have.
theirs = from_langchain(chain, name="researcher")

# Connect it directly to your native Weave agent, no rewrite:
out = await Pipeline([theirs, my_agent]).run("a question")

The default extract pulls text out of common shapes: a str, a BaseMessage (.content), or an agent dict ({"output": ...}). Override it for custom shapes.

CrewAI

from_crewai targets kickoff / kickoff_async. CrewAI's kickoff(inputs=...) takes a dict, so map your Weave value into it with prepare.

from weave import from_crewai

theirs = from_crewai(my_crew, name="writers", prepare=lambda v: {"topic": v})
out = await theirs.run("electric cars")

The default extract returns a str or a CrewOutput.raw.

Anything else: from_callable

If a foreign agent isn't a LangChain/CrewAI object, wrap any sync or async value -> value function. This is the universal escape hatch:

from weave import from_callable

def persons_agent(text: str) -> str:   # could call any SDK, HTTP API, etc.
    return external_sdk.run(text)

theirs = from_callable(persons_agent, name="person_a")

Shaping the boundary

Every bridge accepts two optional callables:

HookSignaturePurpose
prepareweave_value -> foreign_inputadapt the Weave value to what the foreign agent expects
extractforeign_output -> weave_valuepull a Weave-typed value back out

Plus the standard port args: input, output (a DataType or PortSchema), name, and tags. Declare output=DataType.STRUCTURED_JSON when the foreign agent returns a dict you want to flow as structured data.

Extending to a new framework

Each framework is its own module under weave/interop/ that builds on the shared from_callable core. Adding one is a new file (its entrypoint name plus an extract default), never an edit to existing code (Open/Closed).