Skip to main content
Start with the language SDK quickstart first, then move to LangChain once the pact-to-execution flow works without an agent loop.

Before you start

Complete the CLI quickstart first so your runtime already has a paired wallet, API key, and wallet UUID.

5-minute outcome

  1. Build LangChain tools from CoboAgentWalletToolkit
  2. Submit a pact and wait for owner approval
  3. Run an allowed contract-call request
  4. Trigger policy denial from a non-compliant contract call
  5. Retry using denial guidance
  6. Track by request_id and query audit logs

Step 1: Install

pip install "cobo-agentic-wallet[langchain]" langchain-openai

Step 2: Configure environment

export AGENT_WALLET_API_URL=https://api.agenticwallet.cobo.com
export AGENT_WALLET_API_KEY=your-api-key
export OPENAI_API_KEY=your-openai-api-key

Step 3: Wire toolkit and agent

langchain_quickstart.py
import asyncio
import os

from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_openai import ChatOpenAI

from cobo_agentic_wallet.client import WalletAPIClient
from cobo_agentic_wallet.integrations.langchain import CoboAgentWalletToolkit


def main() -> None:
    client = WalletAPIClient(
        base_url=os.environ["AGENT_WALLET_API_URL"],
        api_key=os.environ["AGENT_WALLET_API_KEY"],
    )
    toolkit = CoboAgentWalletToolkit(client=client)
    tools = toolkit.get_tools()

    llm = ChatOpenAI(model="gpt-4.1-mini", temperature=0)
    prompt = ChatPromptTemplate.from_messages([
        (
            "system",
            "Use Cobo wallet tools. Before executing transfers, always submit a pact using "
            "submit_pact and wait until its status is active. If a transfer is denied, read "
            "the denial suggestion, adjust the amount, and retry.",
        ),
        ("human", "{input}"),
        MessagesPlaceholder(variable_name="agent_scratchpad"),
    ])

    agent = create_tool_calling_agent(llm, tools, prompt)
    executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

    wallet_uuid = "your-wallet-uuid"
    destination = "0x1111111111111111111111111111111111111111"

    prompt_text = (
        f"Use wallet {wallet_uuid}. "
        f"First, call submit_pact with intent 'Transfer tokens for testing', permissions "
        f"write:transfer, max_tx 100, and duration 86400. Wait until the pact is active. "
        f"Then transfer 50 USDC to {destination} on BASE. "
        "Then attempt to transfer 200 USDC. If denied, follow the suggestion and retry with "
        "a compliant amount. "
        f"Finally call get_audit_logs for wallet {wallet_uuid} with action transfer.initiate."
    )

    result = executor.invoke({"input": prompt_text})
    print(result)

    asyncio.run(client.close())


if __name__ == "__main__":
    main()
If you want a tighter first integration, start with a smaller tool subset:
toolkit = CoboAgentWalletToolkit(
    client=client,
    include_tools=[
        "submit_pact",
        "get_pact",
        "transfer_tokens",
        "estimate_transfer_fee",
        "get_transaction_record_by_request_id",
        "get_audit_logs",
    ],
)
tools = toolkit.get_tools()

Step 4: Confirm denial loop happened

Verify agent output includes:
  • a pact submission and activation confirmation
  • a successful contract call
  • a policy denial payload/text
  • a corrected retry
  • a transaction lookup by request_id
  • audit log summary

Keep the LangChain layer thin

LangChain should wrap the canonical CAW flow, not replace it with a different mental model.
  • keep CAW tools limited to the exact runtime role
  • keep pact drafting separate from broad wallet management
  • prefer get_transaction_record_by_request_id over ad hoc polling patterns
  • move deterministic business logic outside the model loop when possible

Go further

In Python, CoboAgentWalletToolkit gives you the widened CAW runtime toolkit directly. In TypeScript, the usual pattern is to wrap @cobo/agentic-wallet calls in LangChain tools and expose only the subset your runtime needs.
  • Define custom LangChain tools — in Python, register @tool functions alongside CAW’s adapter; in TypeScript, wrap the CAW SDK in tool(...) definitions with zod schemas.
  • Add CLI tools — call caw via subprocess for operations you want to handle as shell commands rather than Python calls.
  • Use direct SDK calls when determinism matters — for pact lifecycle management, audit queries, or recovery flows, keep the CAW call outside the agent loop.
  • Use role-based presets — a good default split is Pact Drafting, Execution, and Observer. Start narrow and only add more tools when the runtime proves it needs them.

LangChain Integration Details

Error mapping and tool schema behavior.

Python SDK

Use WalletAPIClient directly for custom tool functions.