# Template Agents

> Use existing agents from your workspace.

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

---

Use existing agents from your workspace.

---

## Basic Usage

<div data-type="codegroup">

```python Python
from inferencesh import inference

client = inference(api_key="inf_your_key")

# Reference by namespace/name@version
agent = client.agent("my-team/support-agent@latest")

# Send a message
response = agent.send_message("Hello!")
print(response.text)
```

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

const client = inference({ apiKey: 'inf_your_key' });

const agent = client.agent('my-team/support-agent@latest');

const response = await agent.sendMessage('Hello!');
console.log(response.text);
```

```swift Swift
import InferenceSDK

let client = InferenceClient(apiKey: "inf_your_key")

// Send a message and stream the reply until it finishes
let request = ApiAgentRunRequest(agent: "my-team/support-agent@latest", input: LLMInput(text: "Hello!"))
for try await message in client.runAgentStream(request) {
    if message.status.isTerminal { print(message.text) }
}
```

</div>

---

## Agent Reference Formats

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

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

---

## Per-chat context

Agents declare context fields in their config; you pass values when you start a chat, the same as the CLI's `--context key=value`. The agent writes `{{context.NAME}}` in tool call arguments and the server substitutes the value when the tool runs; call tool URL and header templates use the same placeholders. Values stay out of the system prompt unless the field sets `in_prompt: true`. A declared `default` fills a key you do not send. `required` is not enforced: a chat without the value still runs. See [Context](/docs/agents/adding-tools#context).

<div data-type="codegroup">

```python Python
agent = client.agent(
    "my-team/pricing-agent@latest",
    context={"version_id": "v1", "app_id": "app_123"},
)

response = agent.send_message("Show me the current pricing")
```

```typescript JavaScript
// Imperative SDK
const agent = client.agent('my-team/pricing-agent@latest', {
  context: { version_id: 'v1', app_id: 'app_123' },
});

const response = await agent.sendMessage('Show me the current pricing');

// React AgentChatProvider — include context on agentConfig
<AgentChatProvider
  client={client}
  agentConfig={{
    agent: 'my-team/pricing-agent@latest',
    context: { version_id: 'v1', app_id: 'app_123' },
  }}
>
  <ChatUI />
</AgentChatProvider>
```

</div>

Context is set once per chat and cannot change, so every tool call in that conversation uses the same values.

→ [Context in call tools](/docs/api/agent/call-tools#context) · [Adding tools](/docs/agents/adding-tools#context) · [Create chat REST API](/docs/api/rest/agents#run-agent-recommended)

---

## File attachments

Send images, documents, or other files with a message. The SDK uploads them and attaches `FileRef` URIs to the user message. In React, `AgentChatProvider` / `useAgentActions().sendMessage()` post the refs as `attachments` on `POST /chats/{id}/messages` from **@inferencesh/sdk ≥ v0.22.1**; with an earlier release the files upload but the agent does not see them.

<div data-type="codegroup">

```python Python
# Paths, bytes, or data URIs — uploaded automatically
response = agent.send_message(
    "What's in this image?",
    files=[open("photo.png", "rb").read()],
)

# upload_file returns a FileRef (uri, filename, content_type) for logging or custom flows
ref = agent.upload_file(open("doc.pdf", "rb").read(), filename="doc.pdf")
response = agent.send_message("Summarize this PDF", files=[open("doc.pdf", "rb").read()])
```

```typescript JavaScript
const blob = new Blob([imageBuffer], { type: 'image/png' });

const response = await agent.sendMessage("What's in this image?", {
  files: [blob],
});

// Or pass an existing FileRef (no re-upload)
const ref = await agent.uploadFile(blob, { filename: 'photo.png' });
await agent.sendMessage('Summarize this', { files: [ref] });
```

</div>

→ [Files API](/docs/api/sdk/files) · [Python SDK file attachments](/docs/api/sdk-python#file-attachments) · [JavaScript SDK file attachments](/docs/api/sdk-javascript#file-attachments)

---

## Multi-turn Conversations

State is maintained automatically:

<div data-type="codegroup">

```python Python
agent = client.agent("my-team/support-agent@latest")

response1 = agent.send_message("What's my account status?")
print(response1.text)

response2 = agent.send_message("Can you explain that more?")
print(response2.text)  # Has context from previous message
```

```typescript JavaScript
const agent = client.agent('my-team/support-agent@latest');

const r1 = await agent.sendMessage("What's my account status?");
console.log(r1.text);

const r2 = await agent.sendMessage('Can you explain that more?');
console.log(r2.text);  // Has context from previous message
```

</div>

---

## Reset Conversation

Start a new conversation. `reset()` clears the SDK's chat ID so the next `sendMessage` creates a fresh chat.

When a chat is created, the platform pins the resolved agent version on it (`agent_version_id`). Continuing the same chat always runs that version — redeploying the agent or changing `@latest` in your code does not upgrade an open conversation. Call `reset()` (or start a new chat via REST without `chat_id`) to pick up the latest definition, including updated tool schemas.

<div data-type="codegroup">

```python Python
agent.reset()

response = agent.send_message("Start fresh!")
```

```typescript JavaScript
agent.reset();

const response = await agent.sendMessage('Start fresh!');
```

</div>

---

## Get Chat History

Message history is not included in `GET /chats/:id` or `agent.getChat()`. Fetch messages with the REST [List chat messages](/docs/api/rest/agents#list-chat-messages) endpoint (`GET /chats/:id/messages`). When streaming, `chat_messages` events deliver updates in real time.

With `AgentChatProvider` / `useAgentChat`, the SDK loads messages automatically when connecting or polling (metadata from `GET /chats/:id`, then `GET /chats/:id/messages` when the response has no `chat_messages`). The initial load uses the server default page size (**50 newest messages**) — not the full transcript. Hook state (`chat.chat_messages`) stays populated without extra calls; stream events append new messages during an active run.

**Scroll-back pagination (v0.6.41+):** when `hasOlderMessages` is `true`, call `loadOlderMessages()` from `useAgentActions()` to fetch the next page. The SDK prepends deduplicated messages and updates the internal cursor. Trigger this when the user scrolls near the top of your message list:

```tsx
const { messages } = useAgentChat();
const { loadOlderMessages, hasOlderMessages } = useAgentActions();

// e.g. on scroll near top
if (hasOlderMessages) {
  await loadOlderMessages(); // returns true when more pages remain
}
```

For imperative or non-React UIs, paginate with `cursor` or pass `limit=-1` via the REST API (examples below).

<div data-type="codegroup">

```python Python
# REST: list messages (newest first by default)
messages = client.http.request(
    "get", f"/chats/{chat_id}/messages", params={"limit": -1}
).data["items"]

for message in messages:
    print(f"{message['role']}: {message['content']}")
```

```typescript JavaScript
// REST: list messages (newest first by default)
const { data } = await client.http.request(
  'get',
  `/chats/${chatId}/messages`,
  { params: { limit: -1 } },
);
const messages = data.items;

for (const message of messages) {
  console.log(`${message.role}: ${message.content}`);
}
```

</div>

---

## Stop Active Response

<div data-type="codegroup">

```python Python
# Start streaming
for chunk in agent.send_message("Tell me a story", stream=True):
    if should_stop:
        agent.stop()
        break
    print(chunk.text)
```

```typescript JavaScript
// Start streaming
for await (const chunk of agent.sendMessage('Tell me a story', { stream: true })) {
  if (shouldStop) {
    await agent.stopChat();
    break;
  }
  console.log(chunk.text);
}
```

</div>
