Metadata-Version: 2.5
Name: llama-index-tools-layrcake
Version: 0.1.0
Summary: LlamaIndex tool spec for Layrcake: find leads, enrich and verify emails, check and research companies, and draft campaigns that a person approves before anything sends.
Project-URL: Homepage, https://layrcake.dev
Project-URL: Documentation, https://github.com/Layrcake-dev/llama-index-tools-layrcake#readme
Project-URL: Source, https://github.com/Layrcake-dev/llama-index-tools-layrcake
Project-URL: Issues, https://github.com/Layrcake-dev/llama-index-tools-layrcake/issues
Author-email: Layrcake <founders@layrcake.dev>
Maintainer-email: Layrcake <founders@layrcake.dev>
License-Expression: MIT
License-File: LICENSE
Keywords: agents,layrcake,lead-generation,llama-index,llamaindex,sales,tools
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: <4.0,>=3.10
Requires-Dist: layrcake[agents]<0.3.0,>=0.2.0
Requires-Dist: llama-index-core<0.15,>=0.13.0
Requires-Dist: pydantic<3,>=2.7
Description-Content-Type: text/markdown

# LlamaIndex Tools Integration: Layrcake

A LlamaIndex tool spec for [Layrcake](https://layrcake.dev), go-to-market infrastructure for AI agents. Your agent can find leads, find and verify work emails, check and research companies, and draft email campaigns that a person approves before anything sends.

The tools wrap the official [`layrcake`](https://pypi.org/project/layrcake/) Python SDK.

## Install

```sh
pip install llama-index-tools-layrcake
```

Get an API key at [layrcake.dev/connect](https://layrcake.dev/connect) and set `LAYRCAKE_API_KEY`. New workspaces start with 300 free credits.

## Quickstart

This example also needs a model integration: `pip install llama-index-llms-anthropic`.

```python
import asyncio
from llama_index.core.agent.workflow import FunctionAgent
from llama_index.llms.anthropic import Anthropic
from llama_index.tools.layrcake import LayrcakeToolSpec

tools = LayrcakeToolSpec(budget_credits=50).to_tool_list()  # reads LAYRCAKE_API_KEY
agent = FunctionAgent(tools=tools, llm=Anthropic(model="claude-sonnet-5-5"))

prompt = "Find 5 heads of sales at UK software companies, verify their work emails, draft a campaign, ask for approval."
print(asyncio.run(agent.run(prompt)))
```

The agent stops at an approval link. Nothing is sent until a person approves it in the Layrcake console.

Try it free first: `LayrcakeToolSpec(dry_run=True)` makes every call return its cost instead of data and charges nothing.

### A test run

On 20 October 2026 we ran this quickstart with `OpenRouter(model="anthropic/claude-sonnet-5.5", max_tokens=4096, is_function_calling_model=True)` from `llama-index-llms-openrouter`, `budget_credits=25` and this prompt: "Find 3 heads of sales at software companies in London with 20 to 200 staff, verify their work emails, and draft a short campaign about cutting time spent on lead research."

The agent called `get_me`, `find_leads`, `enrich` three times and `verify_email` twice. One person had no work email, so it called `find_leads`, `enrich` and `verify_email` once more for a replacement, then `create_campaign` and `launch_campaign`. It found 6 people, kept 3 verified emails (1 catch-all) and spent 24.75 of its 25 credits. It stopped at the approval link, and nothing was sent. The run took 50 seconds. That LLM class needs `is_function_calling_model=True` for `FunctionAgent`, and its default `max_tokens` is 256, so we raised it. The draft emails were signed "[Your name]", so edit the sign-off before you approve.

## Tools

| Tool | What it does | Cost |
| --- | --- | --- |
| `find_leads` | Finds people who match an audience: names, titles, companies. No emails. | 0.25 credits per person found, at least 3 when anyone is found. Finding nobody is free. |
| `enrich` | Finds one person's work email from their name and company domain. | 5 credits when found. Free when not. |
| `verify_email` | Checks that an address can receive mail. | 1.25 credits per check. |
| `check_companies` | Answers one yes or no question per company from its own website, with the quote. | 3.5 credits per company answered. Unclear answers are free. |
| `research_company` | Researches one company from public sources and returns dated facts with links. | 9 credits per completed research. |
| `create_campaign` | Saves a draft email campaign for verified people. Drafts never send. | Free. |
| `launch_campaign` | Asks a person to approve the draft. Sends nothing. Returns a preview and an approval link. | Free. |
| `get_me` | Shows the workspace, the credits available and the run budget. | Free. |

1 credit is about $0.01. New workspaces start with 300 free credits. Current prices are at [docs.layrcake.dev/pricing.html](https://docs.layrcake.dev/pricing.html).

You can also call the spec's methods directly:

```python
from llama_index.tools.layrcake import LayrcakeToolSpec

spec = LayrcakeToolSpec(dry_run=True)
print(spec.verify_email("ada@example.com"))
# {"dry_run": true, "would_cost_up_to": "1.25", "would_exceed": [], "warnings": []}
```

## How approval works

Nothing reaches a real person until a person on your side says yes.

1. `create_campaign` saves a draft. A draft never sends.
2. `launch_campaign` asks for approval. It returns `status: "needs_confirmation"`, a preview of what would send and an `approval_url`.
3. A signed-in person opens the link and approves in the Layrcake console. The Layrcake API enforces this step.
4. Only then does the campaign start sending.

The `launch_campaign` tool has no `confirmation_token` argument, and the confirmation token is removed from what the model reads, so an agent cannot approve its own send. After `launch_campaign` asks for approval, the other paid tools in the same run refuse to run, and the agent should stop and report the link.

## Run rules

The tools of one `LayrcakeToolSpec` share a `LayrcakeSession` from `layrcake.agent_tools`, the one implementation of these rules in the Layrcake Python SDK. It applies the rules from [layrcake.dev/agents.md](https://layrcake.dev/agents.md) in code:

- **Budget.** Every paid call sends what is left of the run budget as `budget_credits`, so the API refuses a call that could cost more. Once the budget is spent, paid tools refuse to run. The default budget is 50 credits.
- **Dry run.** With `dry_run=True`, every call returns its plan instead: the most it could cost and any limit it would trip. Nothing is looked up or charged.
- **Idempotency.** Every call sends an idempotency key derived from the run and its arguments. A repeated call returns the first answer instead of charging again. Pass the same `run_id` to resume a run safely.
- **Verified only.** `create_campaign` refuses an address that did not pass `verify_email` in this run (`valid` or `catch_all_valid`). Turn this off with `require_verified=False` if you verify elsewhere.
- **Errors as text.** API errors and refusals come back to the model as text that starts with `Refused:` and says why, such as a spent budget or missing credits, so it can fix the call or stop.

Every call goes through the official [`layrcake`](https://pypi.org/project/layrcake/) Python SDK, which handles authentication, retries and typed errors.

## Configuration

| Argument | Default | Meaning |
| --- | --- | --- |
| `budget_credits` | `50` | The most this run may spend, in credits. |
| `dry_run` | `False` | Return each call's plan instead of running it. Free. |
| `api_key` | `LAYRCAKE_API_KEY` | Your Layrcake API key. |
| `client` | `None` | An existing `layrcake.Layrcake` client, for custom timeouts or proxies. |
| `session` | `None` | An existing `LayrcakeSession`, for `run_id` or `require_verified=False`. |

Use one spec per agent run. Before a live `launch_campaign`, connect sending mailboxes in the [Layrcake console](https://app.layrcake.dev); without them the call returns an error that says what is missing.

## Development

```sh
uv sync
uv run ruff check . && uv run ruff format --check .
uv run mypy
uv run pytest -m "not live"
LAYRCAKE_API_KEY=... uv run pytest -m live   # dry runs only, charges nothing
```

The run rules are tested in the SDK.

## Links

- Layrcake docs: [docs.layrcake.dev](https://docs.layrcake.dev)
- For agents: [layrcake.dev/agents.md](https://layrcake.dev/agents.md)
- MCP server: `https://mcp.layrcake.dev/mcp` (also usable with `llama-index-tools-mcp`)
- Python SDK: [github.com/Layrcake-dev/layrcake-python](https://github.com/Layrcake-dev/layrcake-python)

## License

MIT
