LangChain Integration
Anvil provides seamless integration with LangChain through the to_langchain() adapter.
Installation
Section titled “Installation”pip install "anvil-agent[langchain]"Basic Usage
Section titled “Basic Usage”from anvil import Anvilfrom langchain_anthropic import ChatAnthropicfrom langchain.agents import create_tool_calling_agent, AgentExecutorfrom langchain_core.prompts import ChatPromptTemplate
# Create Anvil toolsanvil = Anvil()
search = anvil.use_tool( name="web_search", intent="Search the web for current information")
weather = anvil.use_tool( name="get_weather", intent="Get current weather for a location")
# Convert to LangChain toolslc_tools = [ search.to_langchain(), weather.to_langchain(),]
# Create LangChain agentllm = ChatAnthropic(model="claude-sonnet-4-20250514")prompt = ChatPromptTemplate.from_messages([ ("system", "You are a helpful assistant."), ("human", "{input}"), ("placeholder", "{agent_scratchpad}"),])
agent = create_tool_calling_agent(llm, lc_tools, prompt)executor = AgentExecutor(agent=agent, tools=lc_tools)
# Runresult = executor.invoke({"input": "What's the weather in Tokyo?"})print(result["output"])How the Adapter Works
Section titled “How the Adapter Works”The to_langchain() method:
- Creates a
BaseToolsubclass - Sets
namefrom your tool name - Sets
descriptionfrom your intent - Generates a Pydantic
args_schemafrom your inputs - Wraps the
run()method for execution
Generated Structure
Section titled “Generated Structure”# Anvil tooltool = anvil.use_tool( name="search_docs", intent="Search documentation for answers", inputs=[ InputParam(name="query", param_type="str", required=True), InputParam(name="limit", param_type="int", default=10), ])
# Converts to approximately:class SearchDocsInput(BaseModel): query: str limit: int = 10
class SearchDocsTool(BaseTool): name = "search_docs" description = "Search documentation for answers" args_schema = SearchDocsInput
def _run(self, query: str, limit: int = 10) -> Any: return anvil_tool.run(query=query, limit=limit)
async def _arun(self, query: str, limit: int = 10) -> Any: return await anvil_tool.run_async(query=query, limit=limit)With Input Parameters
Section titled “With Input Parameters”Define explicit inputs for better type safety:
from anvil import Anvil, InputParam
anvil = Anvil()
calculator = anvil.use_tool( name="calculator", intent="Perform mathematical calculations", inputs=[ InputParam( name="expression", param_type="str", required=True, description="Mathematical expression to evaluate" ), InputParam( name="precision", param_type="int", required=False, default=2, description="Decimal places for the result" ), ])
lc_tool = calculator.to_langchain()
# LangChain will validate inputs against the schemaUsing StructuredTool
Section titled “Using StructuredTool”For more control, use the structured tool variant:
from anvil.adapters.langchain import to_langchain_structured_tool
structured_tool = to_langchain_structured_tool(calculator)This creates a StructuredTool instead of a BaseTool subclass.
With LCEL Chains
Section titled “With LCEL Chains”Use Anvil tools in LangChain Expression Language chains:
from langchain_core.runnables import RunnablePassthrough
# Create toolsresearch = anvil.use_tool(name="research", intent="Research a topic")summarize = anvil.use_tool(name="summarize", intent="Summarize text")
# Build chainchain = ( {"topic": RunnablePassthrough()} | research.to_langchain() | summarize.to_langchain())
result = chain.invoke("quantum computing")Async Execution
Section titled “Async Execution”LangChain tools support async execution:
import asyncio
async def main(): lc_tool = search.to_langchain()
# Async invocation result = await lc_tool.ainvoke({"query": "AI news"}) print(result)
asyncio.run(main())Error Handling
Section titled “Error Handling”Errors from Anvil tools propagate to LangChain:
try: result = executor.invoke({"input": "Search for something"})except Exception as e: print(f"Tool failed: {e}")With self-healing enabled, Anvil will attempt to fix the tool before the error reaches LangChain.
Multiple Tools
Section titled “Multiple Tools”Create multiple tools efficiently:
tools_config = [ ("web_search", "Search the web"), ("calculator", "Perform calculations"), ("file_reader", "Read file contents"),]
lc_tools = []for name, intent in tools_config: tool = anvil.use_tool(name=name, intent=intent) lc_tools.append(tool.to_langchain())
# Use all tools with an agentexecutor = AgentExecutor(agent=agent, tools=lc_tools)Type Mapping
Section titled “Type Mapping”Anvil types map to Python types in the Pydantic schema:
| Anvil Type | Python Type |
|---|---|
str | str |
int | int |
float | float |
bool | bool |
list | list |