# App Tools

> Run inference shell apps as agent tools.

**URL:** https://inference.sh/docs/api/agent/app-tools
**Last updated:** 2026-10-11

---

Run inference shell apps as agent tools.

---

## Basic Usage

<div data-type="codegroup">

```python Python
from inferencesh import app_tool

image_gen = (
    app_tool("generate_image", "infsh/flux@latest")
    .describe("Generate images from text prompts")
    .build()
)
```

```typescript JavaScript
import { appTool } from '@inferencesh/sdk';

const imageGen = appTool('generate_image', 'infsh/flux@latest')
  .describe('Generate images from text prompts')
  .build();
```

</div>

---

## How It Works

When the agent calls an app tool:
1. A task is created for the referenced app
2. Tool arguments become task input
3. Task output becomes tool result
4. Agent continues with the result

---

## Builder Methods

| Method | Description |
|--------|-------------|
| `appTool(name, ref)` | Create app tool with app reference |
| `.describe(text)` | Set description for LLM |
| `.display(name)` | Human-readable name |
| `.setup({...})` | Pre-configured setup values (hidden from agent) |
| `.input({...})` | Default input values (agent can override) |
| `.function(name)` | Specify which function to call (for multi-function apps) |
| `.sessionEnabled()` | Enable session support (agent controls sessions) |
| `.requireApproval()` | Require user approval |
| `.build()` | Build the tool |

---

## App Reference Formats

```
# Latest version
namespace/app-name@latest

# Specific version
namespace/app-name@abc123
```

---

## Examples

### Image Generation

<div data-type="codegroup">

```python Python
image_gen = (
    app_tool("generate_image", "infsh/flux@latest")
    .describe("Generate an image from a text prompt")
    .build()
)

agent = client.agent({
    "core_app": { "ref": "infsh/claude-sonnet-4@latest" },
    "tools": [image_gen]
})

response = agent.send_message("Generate a picture of a sunset")
# Agent calls generate_image, waits for result, then responds
```

```typescript JavaScript
const imageGen = appTool('generate_image', 'infsh/flux@latest')
  .describe('Generate an image from a text prompt')
  .build();

const agent = client.agent({
  core_app: { ref: 'infsh/claude-sonnet-4@latest' },
  tools: [imageGen]
});
```

</div>

### Text-to-Speech & Code Execution

<div data-type="codegroup">

```python Python
tts = (
    app_tool("speak", "infsh/tts@latest")
    .describe("Convert text to speech audio")
    .build()
)

code_runner = (
    app_tool("run_code", "infsh/code-interpreter@latest")
    .describe("Execute Python code and return the result")
    .build()
)
```

```typescript JavaScript
const tts = appTool('speak', 'infsh/tts@latest')
  .describe('Convert text to speech audio')
  .build();

const codeRunner = appTool('run_code', 'infsh/code-interpreter@latest')
  .describe('Execute Python code and return the result')
  .build();
```

</div>

---

## With Approval

<div data-type="codegroup">

```python Python
expensive_model = (
    app_tool("analyze", "expensive/model@latest")
    .describe("Deep analysis using expensive model")
    .require_approval()  # User must approve before running
    .build()
)
```

```typescript JavaScript
const expensiveModel = appTool('analyze', 'expensive/model@latest')
  .describe('Deep analysis using expensive model')
  .requireApproval()
  .build();
```

</div>

---

## Setup & Default Inputs

Configure app tools with pre-set values that persist across calls.

<div data-type="codegroup">

```python Python
# Setup: One-time configuration (API keys, model selection)
# Input: Default values the agent can override

transcribe = (
    app_tool("transcribe", "infsh/whisper@latest")
    .describe("Transcribe audio to text")
    .setup({
        "model": "large-v3",      # Always use this model
        "language": "auto"        # Auto-detect language
    })
    .input({
        "timestamps": True,       # Default: include timestamps
        "format": "srt"           # Default output format
    })
    .build()
)
```

```typescript JavaScript
const transcribe = appTool('transcribe', 'infsh/whisper@latest')
  .describe('Transcribe audio to text')
  .setup({
    model: 'large-v3',
    language: 'auto'
  })
  .input({
    timestamps: true,
    format: 'srt'
  })
  .build();
```

</div>

**How values are merged:**
- **Setup** values are passed on every call — the agent never sees them
- **Input** values are defaults — the agent's arguments override them

---

## Multiple App Tools

<div data-type="codegroup">

```python Python
agent = client.agent({
    "core_app": { "ref": "infsh/claude-sonnet-4@latest" },
    "tools": [
        app_tool("generate_image", "infsh/flux@latest")
            .describe("Generate images").build(),
        app_tool("transcribe", "infsh/whisper@latest")
            .describe("Transcribe audio").build(),
        app_tool("run_code", "infsh/code-interpreter@latest")
            .describe("Run Python code").build(),
    ]
})
```

```typescript JavaScript
const agent = client.agent({
  core_app: { ref: 'infsh/claude-sonnet-4@latest' },
  tools: [
    appTool('generate_image', 'infsh/flux@latest')
      .describe('Generate images').build(),
    appTool('transcribe', 'infsh/whisper@latest')
      .describe('Transcribe audio').build(),
    appTool('run_code', 'infsh/code-interpreter@latest')
      .describe('Run Python code').build(),
  ]
});
```

</div>

---

## Function Selection

For multi-function apps, specify which function to expose as a tool using `.function()`.

<div data-type="codegroup">

```python Python
# Same app, different functions as separate tools
generate = (
    app_tool("generate_image", "infsh/sdxl@latest")
    .describe("Generate an image from a text prompt")
    .function("generate")
    .build()
)

upscale = (
    app_tool("upscale_image", "infsh/sdxl@latest")
    .describe("Upscale an existing image to higher resolution")
    .function("upscale")
    .build()
)

agent = client.agent({
    "core_app": { "ref": "infsh/claude-sonnet-4@latest" },
    "tools": [generate, upscale]
})
```

```typescript JavaScript
const generate = appTool('generate_image', 'infsh/sdxl@latest')
  .describe('Generate an image from a text prompt')
  .function('generate')
  .build();

const upscale = appTool('upscale_image', 'infsh/sdxl@latest')
  .describe('Upscale an existing image to higher resolution')
  .function('upscale')
  .build();

const agent = client.agent({
  core_app: { ref: 'infsh/claude-sonnet-4@latest' },
  tools: [generate, upscale]
});
```

</div>

If not specified, the app's default function is used.

---

## Session Support

Enable session support for stateful interactions where the agent controls session creation and continuation.

<div data-type="codegroup">

```python Python
browser = (
    app_tool("browser", "infsh/browser-use@latest")
    .describe("Control a web browser to navigate and interact with pages")
    .session_enabled()  # Agent can manage sessions
    .build()
)
```

```typescript JavaScript
const browser = appTool('browser', 'infsh/browser-use@latest')
  .describe('Control a web browser to navigate and interact with pages')
  .sessionEnabled()
  .build();
```

</div>

### How Sessions Work

When session support is enabled:

1. Tool schema includes a `session` parameter
2. Agent passes `session: "new"` to start a new session
3. Tool output includes `session_id` (e.g., `sess_abc123`)
4. Agent passes `session: "sess_abc123"` in subsequent calls to continue

### Example Agent Behavior

```
User: "Go to example.com and click the login button"

Agent: [calls browser({action: "navigate", url: "https://example.com", session: "new"})]
> Output: {result: "Page loaded", session_id: "sess_abc123"}

Agent: [calls memory_set(key: "browser_session", value: "sess_abc123")]
> Stored session ID for later use

Agent: [calls browser({action: "click", selector: "#login", session: "sess_abc123"})]
> Output: {result: "Clicked login button", session_id: "sess_abc123"}
```

The agent uses memory tools as per-chat scratch storage to track session IDs across turns in the same chat.
