# GPU tools for agent frameworks

> Give a LangChain, LlamaIndex, OpenAI Agents SDK or Claude Agent SDK agent GPU tools with hard cost caps, and stop its sessions on exit.

Four small Python packages give an agent the Node Lodge GPU tools: list machines, check the balance, launch a session, follow it and stop it. They share one toolkit that holds your cost caps and stops every session the agent launched when your code is done with it.

| Package | Framework |
|---|---|
| `nodelodge-langchain` | LangChain |
| `nodelodge-llamaindex` | LlamaIndex |
| `nodelodge-agents[openai]` | OpenAI Agents SDK |
| `nodelodge-agents[claude]` | Claude Agent SDK |

For agents that speak MCP natively, such as Claude Desktop or Claude Code, use the [MCP server](https://nodelodge.com/docs/mcp) instead.

## The caps

```python
from nodelodge.agent_tools import GpuToolkit

with GpuToolkit(max_cost_usd_per_session=5, max_total_usd=20) as toolkit:
    ...  # give the toolkit's tools to your agent
# every session the agent launched is stopped here
```

- `max_cost_usd_per_session` is required. A launch above it is refused before anything is sent to Node Lodge.
- `max_total_usd` limits the sum of the budgets of the sessions this toolkit launches.
- Node Lodge enforces the limits of the API key on top: give the agent its own key, with **Spending limits**, in **Keys**.
- Leaving the `with` block, calling `toolkit.close()`, or the end of the Python process stops every session the toolkit launched.
- A refusal (a cap, your credit, a limit of the key, an invalid input) reaches the model as an error with a reason, so it can stop and tell you instead of retrying with more.

The key comes from `NODELODGE_API_KEY`, the SSH key from `~/.ssh/id_ed25519.pub`, and the address allowed to connect is your public IPv4 address. Each can be passed to `GpuToolkit` instead.

## LangChain

```python
from langchain.agents import create_agent
from nodelodge_langchain import nodelodge_tools

with GpuToolkit(max_cost_usd_per_session=5) as toolkit:
    agent = create_agent("anthropic:claude-sonnet-5-5", tools=nodelodge_tools(toolkit))
    agent.invoke({"messages": [{"role": "user", "content": "Launch the cheapest GPU with 48 GB of VRAM."}]})
```

## LlamaIndex

```python
from llama_index.core.agent.workflow import FunctionAgent
from nodelodge_llamaindex import nodelodge_tools

with GpuToolkit(max_cost_usd_per_session=5) as toolkit:
    agent = FunctionAgent(tools=nodelodge_tools(toolkit), llm=llm)
    await agent.run("Launch the cheapest GPU with 48 GB of VRAM.")
```

## OpenAI Agents SDK

```python
from agents import Agent, Runner
from nodelodge_agents import openai_agents_tools

with GpuToolkit(max_cost_usd_per_session=5) as toolkit:
    agent = Agent(name="gpu-ops", tools=openai_agents_tools(toolkit))
    result = await Runner.run(agent, "Launch the cheapest GPU with 48 GB of VRAM.")
```

Launching and stopping a session pause the run for your approval (`result.interruptions` in the SDK). Pass `require_approval=False` to let the agent act alone, within the caps.

## Claude Agent SDK

```python
from claude_agent_sdk import ClaudeAgentOptions, query
from nodelodge_agents import claude_allowed_tools, claude_mcp_server

with GpuToolkit(max_cost_usd_per_session=5) as toolkit:
    options = ClaudeAgentOptions(
        mcp_servers={"nodelodge": claude_mcp_server(toolkit)},
        allowed_tools=claude_allowed_tools(["list_offers", "get_balance", "get_session", "list_sessions"]),
    )
    async for message in query(prompt="Launch the cheapest GPU with 48 GB of VRAM.", options=options):
        print(message)
```

The tools run in your process as an in-process MCP server. Pre-approving only the read-only tools, as above, keeps launching and stopping behind the SDK's permission prompt.

## Tools

| Tool | What it does |
|---|---|
| `list_offers` | Machines bookable now, cheapest first, with GPU, VRAM, hourly price and location. |
| `get_balance` | Credit available for a new session, and what the toolkit may still spend. |
| `launch_session` | Starts a machine with a budget. `max_cost_usd` is required, reserved on your credit and capped by the toolkit. Billing follows the real time the machine runs, never past it. |
| `get_session` | Status, cost so far, the launch step while the machine starts (`launch_step`), and the `ssh` command once it runs. |
| `stop_session` | Stops a session: billing stops and the machine and its disk are deleted. |
| `raise_session_budget` | Raises the budget of a running session, within the toolkit's caps and the limits of the key. |
| `list_sessions` | Live or ended sessions. |
