---
title: CrewAI
description: Use @codespar/crewai to give CrewAI agent crews commerce capabilities in Latin America.
---

import { Callout } from "fumadocs-ui/components/callout";
import { Tab, Tabs } from "fumadocs-ui/components/tabs";

# CrewAI Adapter

<VersionBadge pkg="@codespar/crewai" />

The `@codespar/crewai` adapter converts CodeSpar session tools into CrewAI's tool format. Each tool has a `run` method that routes execution through the CodeSpar session for billing and audit. Use it to give your CrewAI crews access to payments, invoicing, shipping, and other commerce operations in Latin America.

<Callout type="info">
**Pick this adapter when** your commerce flow decomposes naturally into specialist roles (a "payments agent", a "fiscal agent", a "logistics agent" collaborating on one order) and you want CrewAI's role-based orchestration to coordinate them.
</Callout>

## Framework-specific notes

- **Tools attached per-agent, not per-crew** — scope payments tools to the payments agent, fiscal tools to the fiscal agent. CrewAI's role-based design pairs well with the meta-tool layer: one role per domain.
- **`.run()` is sync by default** — CrewAI tools expose a `run(input)` method; the adapter wires it to `session.execute` under the hood. For async-heavy commerce flows, prefer the async agent constructor.
- **Delegation between agents** — a Crew with a "research" agent (calls `codespar_discover`) delegating to an "execution" agent (calls `codespar_pay`) models real human-team workflows; the adapter does not need special wiring for this.
- **Memory is CrewAI-native** — CodeSpar sessions expire after 30 min of inactivity, but CrewAI's agent memory (short-term + long-term) persists across runs. Combine for returning-customer scenarios.

## Installation

<Tabs items={["npm", "pnpm", "yarn"]}>
<Tab value="npm">
```bash
npm install @codespar/sdk @codespar/crewai
```
</Tab>
<Tab value="pnpm">
```bash
pnpm add @codespar/sdk @codespar/crewai
```
</Tab>
<Tab value="yarn">
```bash
yarn add @codespar/sdk @codespar/crewai
```
</Tab>
</Tabs>

<Callout type="info">
`@codespar/crewai` has a peer dependency on `@codespar/sdk@^0.10.0`. Make sure it is installed.
</Callout>
## API Reference

### `getTools(session): Promise<CrewAITool[]>`

Fetches all tools from the session and converts them to CrewAI tool format. Each tool has `name`, `description`, `schema` (JSON Schema), and a `run` method.

```typescript
import { CodeSpar } from "@codespar/sdk";
import { getTools } from "@codespar/crewai";

const codespar = new CodeSpar({ apiKey: process.env.CODESPAR_API_KEY });
const session = await codespar.create("user_123", {
  servers: ["stripe", "mercadopago"],
});

const tools = await getTools(session);
console.log(tools[0].name);   // "codespar_charge"
console.log(tools[0].schema); // { type: "object", properties: { ... } }
```

### `toCrewAITool(tool, session): CrewAITool`

Converts a single CodeSpar tool to CrewAI format. The `run` method is bound to the session for execution.

```typescript
import { toCrewAITool } from "@codespar/crewai";

const allTools = await session.tools();
const paymentTools = allTools
  .filter((t) => t.name.includes("pay"))
  .map((t) => toCrewAITool(t, session));
```

### `handleToolCall(session, toolName, args): Promise<ToolResult>`

Convenience executor that routes a tool call through the CodeSpar session.

```typescript
import { handleToolCall } from "@codespar/crewai";

const result = await handleToolCall(session, "codespar_charge", {
  provider: "stripe",
  amount: 4990,
  currency: "BRL",
});
```

## Full agent loop

This is a complete example of a CrewAI crew using CodeSpar tools for commerce operations:

```typescript title="crewai-agent.ts"
import { CodeSpar } from "@codespar/sdk";
import { getTools } from "@codespar/crewai";

const codespar = new CodeSpar({ apiKey: process.env.CODESPAR_API_KEY });

async function run(userMessage: string) {
  // 1. Create a session with the servers you need
  const session = await codespar.create("user_123", {
    servers: ["stripe", "asaas", "correios"],
  });

  // 2. Get tools in CrewAI format
  const tools = await getTools(session);

  // 3. Define your agents
  const paymentAgent = {
    role: "Payment Specialist",
    goal: "Handle all payment operations for Brazilian e-commerce",
    backstory: "Expert in Brazilian payment methods including Pix, boleto, and credit cards.",
    tools,
  };

  const shippingAgent = {
    role: "Shipping Coordinator",
    goal: "Manage shipping and logistics across Brazil",
    backstory: "Expert in Brazilian shipping via Correios and private carriers.",
    tools,
  };

  // 4. Define tasks and create crew
  const task = {
    description: userMessage,
    agent: paymentAgent,
    expectedOutput: "A confirmation of the completed operation with details.",
  };

  // 5. Execute (using your CrewAI runtime)
  // const crew = new Crew({ agents: [paymentAgent, shippingAgent], tasks: [task] });
  // const result = await crew.kickoff();

  // For manual execution:
  for (const tool of tools) {
    if (tool.name === "codespar_charge") {
      const result = await tool.run({
        provider: "stripe",
        amount: 25000,
        currency: "BRL",
        description: "Order #1234",
      });
      console.log("Charge result:", result);
    }
  }

  // 6. Clean up
  await session.close();
}

await run("Process payment of R$250 via Pix for order #1234");
```

## Handling parallel tool calls

When multiple tools need to run concurrently, use `Promise.all` with the `run` method:

```typescript
const results = await Promise.all([
  tools.find((t) => t.name === "codespar_charge")!.run({
    provider: "stripe",
    amount: 4990,
    currency: "BRL",
  }),
  tools.find((t) => t.name === "codespar_notify")!.run({
    channel: "email",
    to: "customer@example.com",
    subject: "Payment received",
  }),
]);
```

## Streaming

CrewAI supports step-by-step callbacks. Use `handleToolCall` in your callbacks to stream tool results:

```typescript title="crewai-callbacks.ts"
import { CodeSpar } from "@codespar/sdk";
import { handleToolCall } from "@codespar/crewai";

const codespar = new CodeSpar({ apiKey: process.env.CODESPAR_API_KEY });
const session = await codespar.create("user_123", {
  servers: ["stripe"],
});

// In your crew step callback:
async function onToolCall(toolName: string, args: Record<string, unknown>) {
  console.log(`Executing: ${toolName}`);
  const result = await handleToolCall(session, toolName, args);
  console.log(`Result:`, result.data);
  return result;
}
```

## Error handling

Wrap `tool.run()` calls in try-catch and return errors as structured data:

```typescript
for (const tool of tools) {
  try {
    const result = await tool.run(input);
    console.log("Success:", result);
  } catch (error) {
    console.error(`Tool ${tool.name} failed:`, error instanceof Error ? error.message : error);
    // Return error to the agent for reasoning
  }
}
```

<Callout type="info">
Returning errors as tool results (instead of throwing) lets the agent reason about the failure and decide whether to retry with different parameters.
</Callout>
## Best practices

1. **Always close sessions.** Use `try/finally` to ensure `session.close()` runs even if the crew throws.

2. **Scope servers narrowly.** Only connect the MCP servers your crew needs. Fewer tools improves agent accuracy.

3. **Assign tools per agent.** Give each agent only the tools relevant to its role instead of sharing all tools across agents.

4. **Set clear goals.** CrewAI agents work best with specific, measurable goals and clear backstories.

5. **Return errors as results.** Let agents reason about failures instead of crashing the crew.

6. **Limit task delegation.** Use `allow_delegation: false` for simple tasks to prevent unnecessary back-and-forth between agents.

## Newer SDK wrappers

`getTools(session)` is the agent-facing path. From any agent task or callback you can also call typed wrappers on the session — same routing, no LLM hop:

- `session.discover(query)` / `session.charge(args)` / `session.pay(args)` / `session.ship(args)` — typed shortcuts for the meta-tools.
- `session.connectionWizard(serverId)` — open a hosted auth flow for a missing connection.
- `session.paymentStatus(toolCallId)` and `session.paymentStatusStream(toolCallId)` — async settlement correlation (poll or SSE).
- `session.verificationStatus(toolCallId)` and `session.verificationStatusStream(toolCallId)` — KYC outcome polling / SSE.

Full reference at [/docs/api/sdk](/docs/api/sdk).

## Next steps

<NextStepsGrid items={[
  { label: "CONCEPT", title: "Sessions", description: "Session lifecycle and configuration.", href: "/docs/concepts/sessions" },
  { label: "CONCEPT", title: "Tools & Meta-Tools", description: "Meta-tools and how routing works.", href: "/docs/concepts/tools" },
  { label: "PROVIDER", title: "AutoGen Adapter", description: "Alternative multi-agent orchestration.", href: "/docs/providers/autogen" },
  { label: "PROVIDER", title: "LangChain Adapter", description: "Single-agent flows with LangChain.js.", href: "/docs/providers/langchain" },
  { label: "QUICKSTART", title: "Quickstart", description: "End-to-end setup in under 5 minutes.", href: "/docs/quickstart" },
]} />
