# LangChain + RentAHuman

Integrate RentAHuman into LangChain agents as custom tools. Build Python and JavaScript AI agents that hire humans for physical tasks with tool calling.

langchain python javascript tool-calling agents llm chain openai anthropic

## LangChain + RentAHuman Integration

LangChain is the most widely used framework for building LLM-powered applications. By defining RentAHuman endpoints as LangChain tools, any LangChain agent — whether backed by GPT-4, Claude, Gemini, or an open-source model — can search for and hire humans for physical-world tasks.

### Why LangChain + RentAHuman

LangChain's tool abstraction makes it straightforward to add real-world capabilities to any agent. You define tools once and they work across all supported LLM providers. The framework's agent executors handle the tool-calling loop, retry logic, and conversation memory automatically. Combined with RentAHuman, you can build agents that reason about what needs to happen in the physical world and then actually make it happen by hiring humans.

### Installation

**Python:**

```bash
pip install langchain langchain-openai requests
```

**JavaScript/TypeScript:**

```bash
npm install langchain @langchain/openai
```

### Python: Define Custom Tools

```python
import requests
from langchain.tools import tool
from langchain_openai import ChatOpenAI
from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain_core.prompts import ChatPromptTemplate
RENTAHUMAN_API = "https://rentahuman.ai/api"
API_KEY = "rah_your_api_key_here"
headers = {"Content-Type": "application/json", "x-api-key": API_KEY}

@tool
def search_humans(query: str, location: str = "") -> str:
    """Search for available humans on RentAHuman marketplace by skills and location.
    Returns a list of matching human profiles with names, skills, rates, and ratings."""
    params = {"q": query, "limit": 10}
    if location:
        params["location"] = location
    resp = requests.get(f"{RENTAHUMAN_API}/search", params=params, headers=headers)
    return resp.text

@tool
def get_human_profile(human_id: str) -> str:
    """Get the full profile of a human including skills, bio, hourly rate,
    availability, location, verification status, and reviews."""
    resp = requests.get(f"{RENTAHUMAN_API}/humans/{human_id}", headers=headers)
    return resp.text

@tool
def create_bounty(title: str, description: str, pay_amount: float, location: str = "") -> str:
    """Post a bounty (task listing) on RentAHuman for humans to apply to.
    Specify the title, detailed description, payment amount in USD, and location if applicable."""
    data = {
        "title": title,
        "description": description,
        "payAmount": pay_amount,
        "payType": "fixed",
        "location": location,
        "isRemote": not bool(location),
    }
    resp = requests.post(f"{RENTAHUMAN_API}/bounties", json=data, headers=headers)
    return resp.text

@tool
def start_conversation(human_id: str, message: str) -> str:
    """Start a new conversation with a human on RentAHuman to discuss task details,
    negotiate rates, or ask questions before hiring."""
    data = {"humanId": human_id, "message": message}
    resp = requests.post(f"{RENTAHUMAN_API}/conversations", json=data, headers=headers)
    return resp.text

@tool
def list_bounty_applications(bounty_id: str) -> str:
    """List all applications submitted by humans for a specific bounty."""
    resp = requests.get(
        f"{RENTAHUMAN_API}/bounties/{bounty_id}/applications", headers=headers
    )
    return resp.text
```

### Python: Create the Agent

```python
tools = [search_humans, get_human_profile, create_bounty, start_conversation, list_bounty_applications]
llm = ChatOpenAI(model="gpt-4o", temperature=0)
prompt = ChatPromptTemplate.from_messages([\
    ("system", """You are a task delegation agent with access to the RentAHuman marketplace.\
When users need something done in the physical world, use the available tools to find\
and hire qualified humans. Always check profiles and ratings before recommending someone.\
Use bounties for tasks where you want multiple applicants. Use direct conversations\
for straightforward bookings."""),\
    ("placeholder", "{chat_history}"),\
    ("human", "{input}"),\
    ("placeholder", "{agent_scratchpad}"),\
])
agent = create_tool_calling_agent(llm, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
result = executor.invoke({
    "input": "I need someone to deliver a birthday cake from Magnolia Bakery to an address in Manhattan. Budget $40.",
    "chat_history": [],
})
print(result["output"])
```

### JavaScript/TypeScript: Define Tools

```typescript
import { tool } from "@langchain/core/tools";
import { z } from "zod";
import { ChatOpenAI } from "@langchain/openai";
import { createToolCallingAgent, AgentExecutor } from "langchain/agents";
import { ChatPromptTemplate } from "@langchain/core/prompts";
const RENTAHUMAN_API = "https://rentahuman.ai/api";
const API_KEY = "rah_your_api_key_here";
const searchHumans = tool(
  async ({ query, location }) => {
    const params = new URLSearchParams({ q: query, limit: "10" });
    if (location) params.set("location", location);
    const resp = await fetch(`${RENTAHUMAN_API}/search?${params}`, {
      headers: { "x-api-key": API_KEY },
    });
    return await resp.text();
  },
  {
    name: "search_humans",
    description: "Search for humans on RentAHuman by skills and location",
    schema: z.object({
      query: z.string().describe("Skills or task description to search for"),
      location: z.string().optional().describe("City or area to search in"),
    }),
  }
);
const createBounty = tool(
  async ({ title, description, payAmount, location }) => {
    const resp = await fetch(`${RENTAHUMAN_API}/bounties`, {
      method: "POST",
      headers: { "Content-Type": "application/json", "x-api-key": API_KEY },
      body: JSON.stringify({
        title,
        description,
        payAmount,
        payType: "fixed",
        location,
        isRemote: !location,
      }),
    });
    return await resp.text();
  },
  {
    name: "create_bounty",
    description: "Post a task bounty for humans to apply to on RentAHuman",
    schema: z.object({
      title: z.string().describe("Short title for the task"),
      description: z.string().describe("Detailed task description"),
      payAmount: z.number().describe("Payment amount in USD"),
      location: z.string().optional().describe("Task location if not remote"),
    }),
  }
);
const tools = [searchHumans, createBounty];
const llm = new ChatOpenAI({ model: "gpt-4o", temperature: 0 });
const prompt = ChatPromptTemplate.fromMessages([\
  ["system", "You are a task delegation agent connected to RentAHuman marketplace."],\
  ["placeholder", "{chat_history}"],\
  ["human", "{input}"],\
  ["placeholder", "{agent_scratchpad}"],\
]);
const agent = createToolCallingAgent({ llm, tools, prompt });
const executor = new AgentExecutor({ agent, tools });
const result = await executor.invoke({
  input: "Find someone in Seattle to pick up a package from a PO box",
  chat_history: [],
});
```

### Common Use Cases

- **Retrieval-augmented action** — Combine RAG for knowledge with RentAHuman tools for physical execution
- **Multi-model agents** — Use Claude for reasoning and GPT-4 for tool calling, both hiring humans via the same tools
- **Chatbot assistants** — Build customer-facing chatbots that can dispatch humans for in-person tasks
- **Workflow automation** — Chain document processing with physical delivery via LangChain's LCEL pipelines

### Best Practices

- **Write detailed tool descriptions** — LangChain agents choose tools based on descriptions. Be specific about what each tool does and when to use it.
- **Use `verbose=True`** — During development, enable verbose mode to see the agent's reasoning about which tools to call and why.
- **Add memory** — Use LangChain's conversation memory so the agent remembers which humans it has already contacted and what tasks are pending.
- **Handle errors gracefully** — Wrap API calls in try/except blocks and return descriptive error messages so the agent can retry or adjust.
- **Rate limit awareness** — Add a small delay between rapid successive tool calls to respect RentAHuman API rate limits.
