> ## Documentation Index
> Fetch the complete documentation index at: https://docs.agent-drop.com/llms.txt
> Use this file to discover all available pages before exploring further.

# CrewAI Integration: AgentDrop File Transfer in CrewAI

> Add AgentDrop as a custom CrewAI tool so multi-agent workflows can send and receive end-to-end encrypted files between agents on different accounts securely.

Use AgentDrop as a custom tool in CrewAI to let your agents send and receive files as part of multi-agent workflows.

## Install Dependencies

```bash theme={null}
pip install crewai requests
```

## Create AgentDrop Tools

Define two CrewAI tools: one for sending files, one for receiving.

```python theme={null}
import os
import requests
from crewai.tools import tool

AGENTDROP_URL = "https://api.agent-drop.com"
AGENTDROP_KEY = os.environ["AGENTDROP_API_KEY"]
HEADERS = {"Authorization": f"Bearer {AGENTDROP_KEY}"}


@tool("Send File via AgentDrop")
def send_file(filepath: str, recipient: str) -> str:
    """Upload a file to AgentDrop for another agent to download.
    Returns the transfer ID."""
    with open(filepath, "rb") as f:
        response = requests.post(
            f"{AGENTDROP_URL}/v1/transfers",
            headers=HEADERS,
            data={
                "sender": "crewai-agent",
                "recipient": recipient,
                "expires_in": "24h",
            },
            files={"files": f},
        )
    response.raise_for_status()
    transfer = response.json()
    return f"Transfer created: {transfer['id']} (expires {transfer['expires_at']})"


@tool("Receive File via AgentDrop")
def receive_file(transfer_id: str, save_as: str) -> str:
    """Download a file from AgentDrop using a transfer ID.
    Saves the file locally and returns the path."""
    response = requests.get(
        f"{AGENTDROP_URL}/v1/transfers/{transfer_id}/download",
        headers=HEADERS,
    )
    response.raise_for_status()

    with open(save_as, "wb") as f:
        f.write(response.content)

    remaining = response.headers.get("X-Downloads-Remaining", "unknown")
    return f"File saved to {save_as} ({remaining} downloads remaining)"
```

## Define Your Agents

```python theme={null}
from crewai import Agent

research_agent = Agent(
    role="Research Analyst",
    goal="Gather data and produce research reports",
    backstory="You are a thorough research analyst who produces detailed reports.",
    tools=[send_file],
    verbose=True,
)

summary_agent = Agent(
    role="Executive Summary Writer",
    goal="Take research reports and produce executive summaries",
    backstory="You distill complex reports into clear executive summaries.",
    tools=[receive_file],
    verbose=True,
)
```

## Build the Crew

```python theme={null}
from crewai import Crew, Task

# Research agent produces a report and uploads it
research_task = Task(
    description=(
        "Research Q1 2026 market trends for AI infrastructure. "
        "Save your findings to 'q1-report.md', then send the file "
        "via AgentDrop to 'summary-agent'."
    ),
    expected_output="Transfer ID of the uploaded report",
    agent=research_agent,
)

# Summary agent downloads the report and summarizes it
summary_task = Task(
    description=(
        "Download the research report using the transfer ID from the "
        "previous task. Read it and produce a 1-page executive summary. "
        "Save the summary to 'exec-summary.md'."
    ),
    expected_output="Path to the executive summary file",
    agent=summary_agent,
)

crew = Crew(
    agents=[research_agent, summary_agent],
    tasks=[research_task, summary_task],
    verbose=True,
)

result = crew.kickoff()
print(result)
```

## What Happens

1. The research agent writes its report to disk
2. It calls `send_file` to upload the report to AgentDrop
3. AgentDrop returns a transfer ID
4. The summary agent receives the transfer ID from the task context
5. It calls `receive_file` to download the report
6. It reads the file and produces the summary

No shared filesystem needed. The agents communicate through AgentDrop's locker model.

## Adding a Status Check Tool

For workflows where timing matters, add a tool to check if a transfer is ready:

```python theme={null}
@tool("Check Transfer Status")
def check_transfer(transfer_id: str) -> str:
    """Check the status of an AgentDrop transfer."""
    response = requests.get(
        f"{AGENTDROP_URL}/v1/transfers/{transfer_id}",
        headers=HEADERS,
    )
    response.raise_for_status()
    transfer = response.json()
    return (
        f"Status: {transfer['status']}, "
        f"Downloads: {transfer['download_count']}/{transfer['max_downloads']}, "
        f"Expires: {transfer['expires_at']}"
    )
```

## Tips

* **Set meaningful sender/recipient names.** They show up in your transfer list and make debugging easier.
* **Use `encrypted=True` for sensitive data.** Add `"encrypted": "true"` to the `data` dict in `send_file`.
* **Set short expiry for ephemeral workflows.** `expires_in="1h"` keeps your storage clean.
* **One transfer per logical unit.** Send related files together in one transfer, not separately.
