Running Agents (Knaps)
Execute Knapsack agents programmatically via API
Running Agents (Knaps)
Execute Knapsack agents programmatically by sending API requests to trigger agent workflows with custom tools and connections.
Overview
The Knap Runs API allows you to:
- Execute pre-configured agents (Knaps) programmatically
- Stream real-time agent execution results
- Provide custom context and tools
- Handle tool approvals and interactions
- Monitor execution progress
Authentication
All requests require authentication using a Bearer token:
Authorization: Bearer YOUR_ACCESS_TOKENSee Authentication for details on obtaining access tokens.
Execute Knap Run
Trigger a Knap run with a user message and available tools.
Endpoint
POST https://api.knapsack.ai/api/knap-tools/runRequest Body
{
"messages": [
{
"role": "user",
"content": "Summarize my emails from last week"
}
],
"tool_types": [
{
"tool_type": "gmail",
"tool_description": "Access Gmail emails"
},
{
"tool_type": "google_calendar",
"tool_description": "Access Google Calendar events"
}
],
"stream_updates": true,
"chat_id": "optional-existing-chat-id",
"use_smart_cache": true,
"knap_tool_uuid": "optional-knap-uuid"
}Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
messages | array | Yes | Array of message objects with role and content |
tool_types | array | Yes | Array of available tools with type and description |
stream_updates | boolean | No | Enable streaming responses (default: true) |
chat_id | string | No | Existing chat ID to continue conversation |
use_smart_cache | boolean | No | Enable smart caching (default: true) |
knap_tool_uuid | string | No | Execute a specific pre-configured Knap |
Response (Streaming)
The API returns a Server-Sent Events (SSE) stream with various event types:
Event Types
1. Tool Execution Events
{
"type": "tool_execution",
"tool_name": "gmail",
"status": "running",
"queryUuid": "abc-123"
}2. Tool Results
{
"type": "tool_result",
"tool_name": "gmail",
"result": {
"emails": [...]
},
"queryUuid": "abc-123"
}3. Agent Messages
{
"type": "message_chunk",
"content": "I found 5 emails from last week...",
"messageId": "msg-456"
}4. Completion
{
"type": "done",
"messageId": "msg-456",
"chatId": "chat-789"
}5. Errors
{
"type": "error",
"error": "Error message",
"details": {...}
}Example Requests
curl -X POST https://api.knapsack.ai/api/knap-tools/run \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"messages": [
{
"role": "user",
"content": "What meetings do I have tomorrow?"
}
],
"tool_types": [
{
"tool_type": "google_calendar",
"tool_description": "Access Google Calendar"
}
],
"stream_updates": true
}'const response = await fetch('https://api.knapsack.ai/api/knap-tools/run', {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
messages: [
{
role: 'user',
content: 'What meetings do I have tomorrow?'
}
],
tool_types: [
{
tool_type: 'google_calendar',
tool_description: 'Access Google Calendar'
}
],
stream_updates: true
})
});
// Handle streaming response
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const events = chunk.split('\n\n').filter(Boolean);
for (const event of events) {
if (event.startsWith('data: ')) {
const data = JSON.parse(event.slice(6));
console.log('Event:', data);
if (data.type === 'done') {
console.log('Execution complete');
}
}
}
}import requests
import json
url = "https://api.knapsack.ai/api/knap-tools/run"
headers = {
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json"
}
payload = {
"messages": [
{
"role": "user",
"content": "What meetings do I have tomorrow?"
}
],
"tool_types": [
{
"tool_type": "google_calendar",
"tool_description": "Access Google Calendar"
}
],
"stream_updates": True
}
with requests.post(url, headers=headers, json=payload, stream=True) as response:
for line in response.iter_lines():
if line:
if line.startswith(b'data: '):
data = json.loads(line[6:])
print(f"Event: {data}")
if data.get('type') == 'done':
print("Execution complete")
breakinterface Message {
role: string;
content: string;
}
interface ToolType {
tool_type: string;
tool_description: string;
}
interface KnapRunRequest {
messages: Message[];
tool_types: ToolType[];
stream_updates?: boolean;
chat_id?: string;
use_smart_cache?: boolean;
knap_tool_uuid?: string;
}
async function executeKnapRun(
accessToken: string,
request: KnapRunRequest
): Promise<void> {
const response = await fetch('https://api.knapsack.ai/api/knap-tools/run', {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(request)
});
if (!response.ok) {
throw new Error(`API error: ${response.statusText}`);
}
const reader = response.body?.getReader();
if (!reader) throw new Error('No response body');
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const events = chunk.split('\n\n').filter(Boolean);
for (const event of events) {
if (event.startsWith('data: ')) {
const data = JSON.parse(event.slice(6));
switch (data.type) {
case 'tool_execution':
console.log(`Tool ${data.tool_name}: ${data.status}`);
break;
case 'message_chunk':
console.log(`Agent: ${data.content}`);
break;
case 'done':
console.log('Execution complete');
return;
case 'error':
console.error('Error:', data.error);
break;
}
}
}
}
}
// Usage
await executeKnapRun(accessToken, {
messages: [
{
role: 'user',
content: 'What meetings do I have tomorrow?'
}
],
tool_types: [
{
tool_type: 'google_calendar',
tool_description: 'Access Google Calendar'
}
],
stream_updates: true
});Execute Pre-configured Knap
Execute a specific pre-configured Knap by UUID:
{
"messages": [
{
"role": "user",
"content": "Run my weekly summary"
}
],
"tool_types": [],
"knap_tool_uuid": "your-knap-uuid",
"stream_updates": true
}When executing a pre-configured Knap, the tool_types array can be empty as the Knap already has its tools configured.
Continuing Conversations
Continue an existing conversation by providing the chat_id:
{
"messages": [
{
"role": "user",
"content": "What about next week?"
}
],
"tool_types": [
{
"tool_type": "google_calendar",
"tool_description": "Access Google Calendar"
}
],
"chat_id": "existing-chat-id",
"stream_updates": true
}Error Handling
Common Error Responses
401 Unauthorized
{
"detail": "Not authenticated"
}400 Bad Request
{
"detail": "Invalid request parameters"
}500 Internal Server Error
{
"type": "error",
"error": "Internal server error",
"details": {...}
}Handling Errors in Stream
Errors during execution are sent as SSE events:
for (const event of events) {
if (event.startsWith('data: ')) {
const data = JSON.parse(event.slice(6));
if (data.type === 'error') {
console.error('Execution error:', data.error);
// Handle error appropriately
}
}
}Rate Limits
API requests are subject to rate limiting. Current limits:
- 100 requests per minute per user
- 1000 requests per hour per organization
Best Practices
1. Handle Streaming Properly
Always handle the stream properly to avoid memory leaks:
const reader = response.body.getReader();
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
// Process chunk
}
} finally {
reader.releaseLock();
}2. Implement Timeout
Set appropriate timeouts for long-running operations:
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 60000); // 60 second timeout
try {
const response = await fetch(url, {
signal: controller.signal,
// ... other options
});
} finally {
clearTimeout(timeout);
}3. Provide Descriptive Tool Descriptions
Help the agent understand available tools:
{
"tool_types": [
{
"tool_type": "gmail",
"tool_description": "Access Gmail emails, search, read, and compose"
},
{
"tool_type": "google_calendar",
"tool_description": "View and manage Google Calendar events"
}
]
}4. Use Smart Caching
Enable smart caching to improve performance:
{
"use_smart_cache": true
}Complete Example
Here's a complete example with proper error handling:
async function runKnapAgent(userMessage: string, tools: ToolType[]) {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 60000);
try {
const response = await fetch('https://api.knapsack.ai/api/knap-tools/run', {
method: 'POST',
signal: controller.signal,
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
messages: [{ role: 'user', content: userMessage }],
tool_types: tools,
stream_updates: true,
use_smart_cache: true
})
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const reader = response.body?.getReader();
if (!reader) throw new Error('No response body');
const decoder = new TextDecoder();
let buffer = '';
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const events = buffer.split('\n\n');
buffer = events.pop() || '';
for (const event of events) {
if (event.startsWith('data: ')) {
try {
const data = JSON.parse(event.slice(6));
handleEvent(data);
if (data.type === 'done') {
return data;
}
} catch (e) {
console.error('Error parsing event:', e);
}
}
}
}
} finally {
reader.releaseLock();
}
} catch (error) {
if (error.name === 'AbortError') {
console.error('Request timed out');
} else {
console.error('Error executing Knap run:', error);
}
throw error;
} finally {
clearTimeout(timeout);
}
}
function handleEvent(data: any) {
switch (data.type) {
case 'tool_execution':
console.log(`🔧 ${data.tool_name}: ${data.status}`);
break;
case 'tool_result':
console.log(`✅ ${data.tool_name} completed`);
break;
case 'message_chunk':
process.stdout.write(data.content);
break;
case 'done':
console.log('\n\n✨ Execution complete');
break;
case 'error':
console.error(`❌ Error: ${data.error}`);
break;
}
}Next Steps
- Authentication - Learn about authentication
- Widget Integration - Embed Knapsack in your app
- Create Knap - Create pre-configured agents
- Webhooks - Set up event notifications