# API Key Management
URL: /api-keys
Secure API key management for agent authentication
***
title: API Key Management
description: Secure API key management for agent authentication
---------------------------------------------------------------
# API Key Management
The Inkeep Agent Framework provides a comprehensive API key management system for authenticating access to agents. API keys are securely hashed and stored, with support for expiration and revocation.
## Overview
API keys provide a secure way to authenticate programmatic access to your agents. Each API key is:
* **Securely hashed** using scrypt algorithm before storage
* **Scoped to a specific tenant and agent**
* **Revocable** at any time
* **Expirable** with optional expiration dates
## Usage
### Creating an API Key
```typescript
import { createApiKey } from '@inkeep/agents-core';
const result = await createApiKey({
tenantId: 'your-tenant-id',
agentId: 'your-agent-id',
expiresAt: '2025-12-31T23:59:59Z', // Optional expiration
});
// IMPORTANT: Show this key to the user only once!
console.log('Your API Key:', result.key);
// Example: sk_live_abc123def456...
// The API key record (without the actual key)
console.log('Key Details:', result.apiKey);
```
# Core concepts
URL: /concepts
Learn about the key building blocks of Inkeep - Agents, Sub Agents, tools, data components, and more.
***
title: Core concepts
sidebarTitle: Concepts
description: Learn about the key building blocks of Inkeep - Agents, Sub Agents, tools, data components, and more.
icon: "LuBoxes"
---------------
## Agents
In Inkeep, an **Agent** is the top-level entity you can interface with via conversational experiences (chat) or trigger programmatically (via API).
Under the hood, an Agent is made up of one or more **Sub Agents** that work together to respond to a user or complete a task.
## Tools
When you send a message to an Agent, it is first received by a **Default Sub Agent** that decides what to do next.
In a simple Agent, there may be only one Sub Agent with a few tools available to it.
**Tools** are actions that a Sub Agent can take, like looking up information or performing a task on apps and APIs.
In Inkeep, tools can be added to Sub Agents as:
* **MCP Servers**: Connect to external services and APIs via the Model Context Protocol. You can:
* **Connect to Native MCP servers** provided directly by SaaS vendors (no building required)
* **Access Composio's platform** for 10,000+ out-of-box MCP servers for popular services (no building required)
* **Use Gram** to convert OpenAPI specs into MCP servers
* **Build and deploy Custom servers** for your own APIs and business logic
Register any of these with their associated **Credentials** for your Agents to use.
* **Function Tools**: Custom JavaScript functions that Agents can execute directly without the need for standing up an MCP server.
Typically, you want a Sub Agent to handle narrow, well-defined tasks. As a general rule of thumb, keep Sub Agents to be using 5-7 related tools at a time.
## Sub Agent relationships
When your scenario gets complex, it can be useful to break up your logic into multiple Sub Agents that are specialized in specific parts of your task or workflow. This is often referred to as a "Multi-agent" system.
A Sub Agent can be configured to:
* **Transfer** control of the chat to another Sub Agent. When a transfer happens, the receiving Sub Agent becomes the primary driver of the thread and can respond to the user directly.
* **Delegate** a subtask for another ('child') Sub Agent to do and wait for its response before proceeding with the next step. A child Sub Agent *cannot* respond directly to a user.
## Sub Agent 'turn'
When it's a Sub Agent's turn, it can choose to:
1. Send an update message to the user
2. Call a tool to collect information or take an action
3. Transfer or delegate to another Sub Agent
An Agent's execution stays in this loop until one of the Sub Agents chooses to respond to the user with a final result.
Sub Agents in Inkeep are designed to respond to the user as a single, cohesive unit by default.
## Chatting with an Agent
<>
You can talk to an Inkeep Agent in a few ways, including:
* **UI Chat Components**: Drop-in React components for chat UIs with built-in streaming and rich UI customization. See [`agents-ui`](/talk-to-your-agents/react/chat-button).
* **As an MCP server**: Use your Inkeep Agent as if was an MCP Server. Allows you to connect it to any MCP client, like Claude, ChatGPT, Claude and other Agents. See [MCP server](/talk-to-your-agents/mcp-server).
* **Via API (Vercel format)**: An API that streams responses over server-side events (SSE). Use from any language/runtime, including the Vercel's `useChat` and AI Element primitives for custom UIs. See [API (Vercel format)](/talk-to-your-agents/api).
* **Via API (A2A format)**: An API that follows the Agent-to-Agent ('A2A') JSON-RPC protocol. Great for when combining Inkeep with different Agent frameworks that support the A2A format. See [A2A protocol](/talk-to-your-agents/a2a).
Drop-in chat components for React apps with streaming and rich UI.
POST /api/chat, SSE (text/event-stream), x-vercel-ai-data-stream: v2.
JSON-RPC messages at /agents/a2a with blocking and streaming modes.
HTTP JSON-RPC endpoint at /v1/mcp with session header management.
>
## Authentication & API Keys
You can authenticate with your Agent using:
* **API Keys**: Securely hashed keys that are scoped to specific Agents
* **Development Mode**: No API key required, perfect for local development and testing
* **Bypass Secrets**: For internal services and infrastructure that need direct access
API keys are the recommended approach for production use, providing secure, scoped access to your Agents.
## Agent replies with Structured Data
Sometimes, you want your Agent to reply not in plain text but with specific types of well-defined information, often called 'Structured Outputs' (JSON).
With Inkeep, there are a few ways to do this:
* **Data Components**: Structured Outputs that Sub Agents can output in their messages so they can render rich, interactive UIs (lists, buttons, forms, etc.) or convey structured information.
* **Artifacts**: A Sub Agent can save information from a **tool call result** as an artifact in order to make it available to others. For example, a Sub Agent that did a web search can save the contents of a webpage it looked at as an artifact. Once saved, a Sub Agent can cite or reference artifacts in its response, and other Sub Agents or users can fetch the full artifacts if they'd like.
* **Status Updates**: Real-time progress updates that can be plain text or Structured Outputs that can be used to keep users informed about what the Sub Agent is doing during longer operations.
## Passing context to Sub Agents
Beyond using Tools to fetch information, Sub Agents also receive information via:
* **Headers**: In the API request to an Agent, the calling application can include headers for a Sub Agent. Learn more [here](/typescript-sdk/headers).
* **Context Fetchers**: Can be configured for an Agent so that at the beginning of a conversation, an API call is automatically made to an external service to get information that is then made available to any Sub Agent. For example, your Headers may include a `user-id`, which can be used to auto-fetch information from a CRM about the user for any Sub Agent to use.
Headers and fetched context can then be referenced explicitly as `{{variables}}` in Sub Agent prompts. Learn more [here](/typescript-sdk/headers).
## Ways to build
Quick reference to the key docs for building with the Visual Builder or the TypeScript SDK.
Configure and manage MCP servers for your Sub Agents.
Create and manage Agents visually.
Build rich UI elements Sub Agents can render in conversations.
Define structured outputs generated by tools or Sub Agents.
Show progress updates during longer operations.
Manage secrets and auth for MCP servers.
Organize agents, MCP Servers, and other entities in Projects.
Configure Sub Agents with prompts, tools, and data components.
Add tools as MCP servers.
Create custom JavaScript functions that run in secure sandboxes.
Define how Sub Agents transfer and delegate tasks.
Build custom UI elements Sub Agents can render.
Create structured outputs from tools or Sub Agents.
Provide real-time progress updates.
Dynamically fetch and cache external context.
Store and retrieve credentials for MCP tools.
The Visual Builder and TypeScript SDK work seamlessly together—define your Sub Agents in code, push them to the Visual Builder, and iterate visually.
## Projects
You can organize your related MCP Servers, Credentials, Agents, and more into **Projects**. A Project is generally used to represent a set of related scenarios.
For example, you may create one Project for your support team that has all the MCP servers and Agents related to customer support.
## CLI: Push and pull
The Inkeep CLI bridges your TypeScript SDK project and the Visual Builder.
Run the following from your project (the folder that contains your `inkeep.config.ts`) which has an `index.ts` file that exports a project.
* **Push (code → Builder)**: Sync locally defined agents, Sub Agents, tools, and settings from your SDK project into the Visual Builder.
```bash
inkeep push
```
* **Pull (Builder → code)**: Fetch your project from the Visual Builder back into your SDK project. By default, the CLI will LLM-assist in updating your local TypeScript files to reflect Builder changes.
```bash
inkeep pull
```
Push and pull operate at the project level (not individual agents). Define agents in your project and push/pull the whole project.
See the [CLI Reference](/typescript-sdk/cli-reference) for full command details.
## Deployment
Once you've built your Agents, you can deploy them using:
Self-host your Agents using Docker for full control and flexibility.
Deploy your Agents to Vercel for easy serverless hosting.
## Architecture
The Inkeep Agent framework is composed of several key services and libraries that work together:
* **agents-manage-api**: An API that handles configuration of Agents, Sub Agents, MCP Servers, Credentials, and Projects with a REST API.
* **agents-manage-ui**: Visual Builder web interface for creating and managing Agents. Writes to the `agents-manage-api`.
* **agents-sdk**: TypeScript SDK (`@inkeep/agents-sdk`) for declaratively defining Agents and custom tools in code. Writes to `agents-manage-api`.
* **agents-cli**: Includes various handy utilities, including `inkeep push` and `inkeep pull` which sync your TypeScript SDK code with the Visual Builder.
* **agents-run-api**: The Runtime API that exposes Agents as APIs and executes Agent conversations. Keeps conversation state and emits OTEL traces.
* **agents-ui**: A UI component library of chat interfaces for embedding rich, dynamic conversational AI experiences in web apps.
# The No-Code + Code Agent Builder
URL: /overview
Inkeep is a platform for building Agent Chat Assistants and AI Workflows.
***
title: The No-Code + Code Agent Builder
sidebarTitle: Overview
icon: "LuBookOpen"
description: Inkeep is a platform for building Agent Chat Assistants and AI Workflows.
--------------------------------------------------------------------------------------
With Inkeep, you can build AI Agents with a **No-Code Visual Builder** and **Developer SDK**. Agents can be edited in either with **full 2-way sync**, so technical and non-technical teams can create and manage their Agents in one platform.
## Two ways to build
### No-Code Visual Builder
A drag-and-drop canvas so any team can create and own the Agents they care about.
### TypeScript Agents SDK
A code-first framework so engineering teams can build with the tools they expect.
```typescript
import { agent, subAgent } from "@inkeep/agents-sdk";
import { consoleMcp } from "./mcp";
const helloAgent = subAgent({
id: "hello-agent",
name: "Hello Agent",
description: "Says hello",
canUse: () => [consoleMcp],
prompt: `Reply to the user and console log "hello world" with fun variations like h3llo world`,
});
export const basicAgent = agent({
id: "basic-agent",
name: "Basic Agent",
description: "A basic agent",
defaultSubAgent: helloAgent,
subAgents: () => [helloAgent],
});
```
The **Visual Builder and TypeScript SDK are fully interoperable**: your technical and non-technical teams can edit and manage Agents in either format and switch or collaborate with others at any time.
## Use cases
Inkeep Agents can operate as **Agentic AI Chat Assistants**, for example:
* a customer experience agent for help centers, technical docs, or in-app experiences
* an internal copilot to assist your support, sales, marketing, ops, and other teams
Agents can also be used for **Agentic Workflow Automation** like:
* Creating and updating knowledge bases, documentation, and blogs
* Updating CRMs, triaging helpdesk tickets, and tackling repetitive tasks
## Platform Overview
**Inkeep Open Source** includes:
* A Visual Builder & TypeScript SDK with 2-way sync
* Multi-agent architecture to support teams of agents
* MCP Tools with credentials management
* A UI component library for dynamic chat experiences
* Triggering Agents via MCP, A2A, & Vercel SDK APIs
* Observability via a Traces UI & OpenTelemetry
* Easy deployment to Vercel and using Docker
Interested in a managed platform? Sign up for the [Inkeep Cloud waitlist](https://inkeep.com/cloud-waitlist) or learn about [Inkeep Enterprise](https://inkeep.com/enterprise). You can view a full feature comparison [here](/pricing#feature-comparison).
## Our Approach
Inkeep is designed to be extensible and open: you can use the LLM provider of your choice, use Agents via open protocols, and with a [fair-code](/community/license) license and great devex, easily deploy and self-host Agents in your own infra.
[Join our community](https://docs.inkeep.com/community/inkeep-community) to get support, stay up to date, and share feedback.
## Next Steps
Get started with the Visual Builder and TypeScript SDK in under 5 minutes.
Learn about the key concepts of building Agents with Inkeep.
# Pricing
URL: /pricing
Learn about Inkeep's pricing plans and features
***
title: Pricing
description: Learn about Inkeep's pricing plans and features
icon: "LuCreditCard"
--------------------
Inkeep offers three ways to get started: **Open Source** (free forever), **Cloud** (managed deployment), and **Enterprise** (managed platform with dedicated support).
Everything you need to create agentic assistants.
* Visual Builder & SDK
* MCP Servers & Tools
* Observability & UI Lib
* Use with Claude/Cursor
* Deploy to Vercel or Docker
Follow the \<1min Quick Start →
Managed deployment with usage-based billing. Everything in Open Source plus:
* Fully managed cloud hosting
* No infra management
* Transparent, usage-based pricing
Sign up for the Cloud waitlist →
Managed platform with dedicated support. Everything in Open Source plus:
* Unified AI Search (Managed RAG)
* Use from Slack & Support Platforms
* PII removal and data controls
* Cloud Hosting & User Management
* Trainings, enablement, and support
* Dedicated forward deployed engineer
Schedule a Demo →
## Feature Comparison
### Building Agents
| Feature | Open Source | Cloud | Enterprise |
| -------------------------------- | :---------: | :---: | :--------: |
| No-Code Visual Builder | ✓ | ✓ | ✓ |
| Agent Developer SDK (TypeScript) | ✓ | ✓ | ✓ |
| 2-way Sync: Edit in Code or UI | ✓ | ✓ | ✓ |
### Core Framework
| Feature | Open Source | Cloud | Enterprise |
| ------------------------------------------------------ | :---------: | :---: | :--------: |
| Take actions on any MCP Server, App, or API | ✓ | ✓ | ✓ |
| Multi-agent Architecture (Teams of Agents) | ✓ | ✓ | ✓ |
| Agent Credential and Permissions Management | ✓ | ✓ | ✓ |
| Agent Traces available in UI and OTEL | ✓ | ✓ | ✓ |
| Talk to Agents via A2A, MCP, and Vercel AI SDK formats | ✓ | ✓ | ✓ |
### Talk to Your Agents (Out of the Box)
| Feature | Open Source | Cloud | Enterprise |
| -------------------------------------------------- | :---------: | :---: | :--------: |
| With Claude, ChatGPT, and Cursor | ✓ | ✓ | ✓ |
| With Slack, Discord, and Teams integrations | — | — | ✓ |
| With Zendesk, Salesforce, and support integrations | — | — | ✓ |
### Building Agent UIs
| Feature | Open Source | Cloud | Enterprise |
| --------------------------------------------------- | :---------: | :---: | :--------: |
| Agent Messages with Custom UIs (forms, cards, etc.) | ✓ | ✓ | ✓ |
| Custom UIs using Vercel AI SDK format | ✓ | ✓ | ✓ |
| Out-of-box Chat Components (React) | ✓ | ✓ | ✓ |
| Out-of-box Chat Components (JavaScript) | — | — | ✓ |
| Answers with Inline Citations | ✓ | ✓ | ✓ |
### Unified AI Search (Managed RAG)
| Feature | Open Source | Cloud | Enterprise |
| ---------------------------------------------------- | :---------: | :---: | :--------: |
| Real-time fetch from databases, APIs, and the web | ✓ | ✓ | ✓ |
| Public sources ingestion (docs, help center, etc.) | — | — | ✓ |
| Private sources ingestion (Notion, Confluence, etc.) | — | — | ✓ |
| Optimized Retrieval and Search (Managed RAG) | — | — | ✓ |
| Semantic Search | — | — | ✓ |
### Insights & Analytics
| Feature | Open Source | Cloud | Enterprise |
| ---------------------------------- | :---------: | :---: | :--------: |
| AI Reports on Knowledge Gaps | — | — | ✓ |
| AI Reports on Product Feature Gaps | — | — | ✓ |
### Authentication and Authorization
| Feature | Open Source | Cloud | Enterprise |
| ------------------------- | :---------: | :---: | :--------: |
| Single Sign-on | — | — | ✓ |
| Role-Based Access Control | — | — | ✓ |
| Audit Logs | — | — | ✓ |
### Security
| Feature | Open Source | Cloud | Enterprise |
| ------------------------------------- | :---------: | :---: | :--------: |
| PII Removal | — | — | ✓ |
| Uptime and Support SLAs | — | — | ✓ |
| SOC II Type II and Pentest Reports | — | — | ✓ |
| GDPR, HIPAA, DPA, and Infosec Reviews | — | — | ✓ |
### Deployment
| Feature | Open Source | Cloud | Enterprise |
| ------------- | :---------: | :-------: | :---------------------------: |
| Hosting Types | Self-hosted | Cloud | Cloud, Hybrid, or Self-hosted |
| Support Type | Community | Community | Dedicated Engineering Team |
### Forward Deployed Engineer Program
| Feature | Open Source | Cloud | Enterprise |
| ------------------------------------------ | :---------: | :---: | :--------: |
| Dedicated Architect and AI Agents Engineer | — | — | ✓ |
| 1:1 Office Hours and Trainings | — | — | ✓ |
| Structured Pilot | — | — | ✓ |
# Troubleshooting Guide
URL: /troubleshooting
Learn how to diagnose and resolve issues when something breaks in your Inkeep agent system.
***
title: Troubleshooting Guide
sidebarTitle: Troubleshooting
description: Learn how to diagnose and resolve issues when something breaks in your Inkeep agent system.
icon: LuWrench
keywords: troubleshooting, debugging, errors, timeline, signoz, widget implementation
-------------------------------------------------------------------------------------
## Overview
This guide provides a structured methodology for debugging problems across different components of your agent system.
## Step 1: Check the Timeline
The timeline is your first stop for understanding what happened during a conversation or agent execution. Navigate to the **Traces** sections to view in depth details per conversation. Within each conversation, you'll find an **error card** that is clickable whenever something goes wrong during agent execution.
### What to Look For
* **Execution flow**: Review the sequence of agent actions and tool calls
* **Timing**: Check for delays or bottlenecks in the execution
* **Agent transitions**: Verify that transfers and delegations happened as expected
* **Tool usage**: Confirm that tools were called correctly and returned expected results
* **Error cards**: Look for red error indicators in the timeline and click to view detailed error information
### Error Cards in the Timeline
Clicking on this error card reveals:
* **Error type**: The specific category of error (e.g., "Agent Generation Error")
* **Exception stacktrace**: The complete stack trace showing exactly where the error occurred in the code
This detailed error information helps you pinpoint exactly what went wrong and where in your agent's execution chain.
<>
### Copy Trace for Debugging
The `Copy Trace` button in the timeline view allows you to export the entire conversation trace as JSON. This is particularly useful for offline analysis and debugging complex flows.
#### What's Included in the Trace Export
When you click `Copy Trace`, the system exports a JSON object containing:
```json
{
"metadata": {
"conversationId": "unique-conversation-id",
"traceId": "distributed-trace-id",
"agentId": "agent-identifier",
"agentName": "Agent Name",
"exportedAt": "2025-10-14T12:00:00.000Z"
},
"timing": {
"startTime": "2025-10-14T11:59:00.000Z",
"endTime": "2025-10-14T12:00:00.000Z",
"durationMs": 60000
},
"timeline": [
// Array of all activities with complete details:
// - Agent messages and responses
// - Tool calls and results
// - Agent transfers
// - Artifact information
// - Execution context
]
}
```
#### How to Use Copy Trace
1. Navigate to the **Traces** section in the management UI
2. Open the conversation you want to debug
3. Click the **Copy Trace** button at the top of the timeline
4. The complete trace JSON is copied to your clipboard
5. Paste it into your preferred tool for analysis
This exported trace contains all the activities shown in the timeline, making it easy to share complete execution context with team members or support.
>
## Step 2: Check SigNoz
SigNoz provides distributed tracing and observability for your agent system, offering deeper insights when the built-in timeline isn't sufficient.
### Accessing SigNoz from the Timeline
You can easily access SigNoz directly from the timeline view. In the **Traces** section, click on any activity in the conversation timeline to view its details. Within the activity details, you'll find a **"View in SigNoz"** button that takes you directly to the corresponding span in SigNoz for deeper analysis.
### What SigNoz Shows
* **Distributed traces**: End-to-end request flows across services
* **Performance metrics**: Response times, throughput, and error rates
### Key Metrics to Monitor
* **Agent response times**: How long each agent takes to process requests
* **Tool execution times**: Performance of MCP servers and external APIs
* **Error rates**: Frequency and types of failures
## Agent Stopped Unexpectedly
### StopWhen Limits Reached
If your agent stops mid-conversation, it may have hit a configured stopWhen limit:
* **Transfer limit reached**: Check `transferCountIs` on your Agent or Project - agent stops after this many transfers between Sub Agents
* **Step limit reached**: Check `stepCountIs` on your Sub Agent or Project - execution stops after this many tool calls + LLM responses
**How to diagnose:**
* Check the timeline for the last activity before stopping
* Look for messages indicating limits were reached
* Review your stopWhen configuration in Agent/Project settings
**How to fix:**
* Increase the limits if legitimate use case requires more steps/transfers
* Optimize your agent flow to use fewer transfers
* Investigate if agent is stuck in a loop (limits working as intended)
See [Configuring StopWhen](/typescript-sdk/agent-settings#configuring-stopwhen) for more details.
## Check service logs (local development)
When running `pnpm dev` from your [quickstart workspace](/quick-start/start-development), you will see an interactive terminal interface. This interface allows you to inspect the logs of each [running service](/quick-start/start-development#service-ports). You can navigate between services using the up and down arrow keys.

* The `service-info` tab displays the health of each running service.
* The `manage-api` tab contains logs for all database operations. This is useful primarily for debugging issues with [`inkeep push`](/typescript-sdk/push-pull-workflows).
* The `run-api` tab contains logs for all agent execution and tool calls. This is useful for debugging issues with your agent's behavior.
* The `mcp` tab contains logs for your [custom MCP servers](/tutorials/how-to-create-mcp-servers/inkeep).
* The `dashboard` tab displays logs for the [Visual Builder](/visual-builder/overview) dashboard.
To terminate the running services, click press `q` or `esc` in the terminal.
## Common Configuration Issues
### General Configuration Issues
* **Missing environment variables**: Ensure all required env vars are set
* **Incorrect API endpoints**: Verify you're using the right URLs
* **Network connectivity**: Check firewall and proxy settings
* **Version mismatches**: Ensure all packages are compatible
### MCP Server Connection Issues
* **MCP not able to connect**:
* Check that the MCP server is running and accessible
* **401 Unauthorized errors**:
* Verify that credentials are properly configured and valid
* **Connection timeouts**:
* Ensure network connectivity and firewall settings allow connections
### AI Provider Configuration Problems
* **AI Provider key not defined or invalid**:
* Ensure you have one of these environment variables set: `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, or `GOOGLE_GENERATIVE_AI_API_KEY`
* Verify the API key is valid and has sufficient credits
* Check that the key hasn't expired or been revoked
* **GPT-5 access issues**:
* Individual users cannot access GPT-5 as it requires organization verification
* Use GPT-4 or other available models instead
* Contact OpenAI support if you need GPT-5 access for your organization
### Credit and Rate Limiting Issues
* **Running out of credits**:
* Monitor your OpenAI usage and billing
* Set up usage alerts to prevent unexpected charges
* **Rate limiting by AI providers**:
* Especially common with high-frequency operations like summarizers
* Monitor your API usage patterns and adjust accordingly
### Context Fetcher Issues
* **Context fetcher timeouts**:
* Check that external services are responding within expected timeframes
# Inkeep Agents Manage API
URL: /api-reference
undefined
***
title: Inkeep Agents Manage API
full: true
\_openapi:
toc:
* depth: 2
title: List Projects
url: '#list-projects'
* depth: 2
title: Create Project
url: '#create-project'
* depth: 2
title: Get Project
url: '#get-project'
* depth: 2
title: Update Project
url: '#update-project'
* depth: 2
title: Delete Project
url: '#delete-project'
* depth: 2
title: List SubAgents
url: '#list-subagents'
* depth: 2
title: Create SubAgent
url: '#create-subagent'
* depth: 2
title: Get SubAgent
url: '#get-subagent'
* depth: 2
title: Delete SubAgent
url: '#delete-subagent'
* depth: 2
title: Update SubAgent
url: '#update-subagent'
* depth: 2
title: List Agent Relations
url: '#list-agent-relations'
* depth: 2
title: Create Agent Relation
url: '#create-agent-relation'
* depth: 2
title: Get Agent Relation
url: '#get-agent-relation'
* depth: 2
title: Delete Agent Relation
url: '#delete-agent-relation'
* depth: 2
title: Update Agent Relation
url: '#update-agent-relation'
* depth: 2
title: List Agent Agent
url: '#list-agent-agent'
* depth: 2
title: Create Agent Agent
url: '#create-agent-agent'
* depth: 2
title: Get Agent Agent
url: '#get-agent-agent'
* depth: 2
title: Delete Agent Agent
url: '#delete-agent-agent'
* depth: 2
title: Update Agent Agent
url: '#update-agent-agent'
* depth: 2
title: Get Related Agent Infos
url: '#get-related-agent-infos'
* depth: 2
title: Get Full Agent Definition
url: '#get-full-agent-definition'
* depth: 2
title: List SubAgent Tool Relations
url: '#list-subagent-tool-relations'
* depth: 2
title: Create SubAgent Tool Relation
url: '#create-subagent-tool-relation'
* depth: 2
title: Get SubAgent Tool Relation
url: '#get-subagent-tool-relation'
* depth: 2
title: Delete SubAgent Tool Relation
url: '#delete-subagent-tool-relation'
* depth: 2
title: Update SubAgent Tool Relation
url: '#update-subagent-tool-relation'
* depth: 2
title: Get SubAgents for Tool
url: '#get-subagents-for-tool'
* depth: 2
title: Get Artifact Components for Agent
url: '#get-artifact-components-for-agent'
* depth: 2
title: Get Agents Using Artifact Component
url: '#get-agents-using-artifact-component'
* depth: 2
title: Associate Artifact Component with Agent
url: '#associate-artifact-component-with-agent'
* depth: 2
title: Remove Artifact Component from Agent
url: '#remove-artifact-component-from-agent'
* depth: 2
title: Check if Artifact Component is Associated with Agent
url: '#check-if-artifact-component-is-associated-with-agent'
* depth: 2
title: Get Data Components for Agent
url: '#get-data-components-for-agent'
* depth: 2
title: Get Agents Using Data Component
url: '#get-agents-using-data-component'
* depth: 2
title: Associate Data Component with Agent
url: '#associate-data-component-with-agent'
* depth: 2
title: Remove Data Component from Agent
url: '#remove-data-component-from-agent'
* depth: 2
title: Check if Data Component is Associated with Agent
url: '#check-if-data-component-is-associated-with-agent'
* depth: 2
title: List Artifact Components
url: '#list-artifact-components'
* depth: 2
title: Create Artifact Component
url: '#create-artifact-component'
* depth: 2
title: Get Artifact Component
url: '#get-artifact-component'
* depth: 2
title: Delete Artifact Component
url: '#delete-artifact-component'
* depth: 2
title: Update Artifact Component
url: '#update-artifact-component'
* depth: 2
title: List Context Configurations
url: '#list-context-configurations'
* depth: 2
title: Create Context Configuration
url: '#create-context-configuration'
* depth: 2
title: Get Context Configuration
url: '#get-context-configuration'
* depth: 2
title: Delete Context Configuration
url: '#delete-context-configuration'
* depth: 2
title: Update Context Configuration
url: '#update-context-configuration'
* depth: 2
title: List Credentials
url: '#list-credentials'
* depth: 2
title: Create Credential
url: '#create-credential'
* depth: 2
title: Get Credential
url: '#get-credential'
* depth: 2
title: Delete Credential
url: '#delete-credential'
* depth: 2
title: Update Credential
url: '#update-credential'
* depth: 2
title: List Data Components
url: '#list-data-components'
* depth: 2
title: Create Data Component
url: '#create-data-component'
* depth: 2
title: Get Data Component
url: '#get-data-component'
* depth: 2
title: Delete Data Component
url: '#delete-data-component'
* depth: 2
title: Update Data Component
url: '#update-data-component'
* depth: 2
title: List External Agents
url: '#list-external-agents'
* depth: 2
title: Create External Agent
url: '#create-external-agent'
* depth: 2
title: Get External Agent
url: '#get-external-agent'
* depth: 2
title: Delete External Agent
url: '#delete-external-agent'
* depth: 2
title: Update External Agent
url: '#update-external-agent'
* depth: 2
title: List Function Tools
url: '#list-function-tools'
* depth: 2
title: Create Function Tool
url: '#create-function-tool'
* depth: 2
title: Get Function Tool by ID
url: '#get-function-tool-by-id'
* depth: 2
title: Delete Function Tool
url: '#delete-function-tool'
* depth: 2
title: Update Function Tool
url: '#update-function-tool'
* depth: 2
title: List Functions
url: '#list-functions'
* depth: 2
title: Create Function
url: '#create-function'
* depth: 2
title: Get Function by ID
url: '#get-function-by-id'
* depth: 2
title: Delete Function
url: '#delete-function'
* depth: 2
title: Update Function
url: '#update-function'
* depth: 2
title: List Tools
url: '#list-tools'
* depth: 2
title: Create Tool
url: '#create-tool'
* depth: 2
title: Get Tool
url: '#get-tool'
* depth: 2
title: Delete Tool
url: '#delete-tool'
* depth: 2
title: Update Tool
url: '#update-tool'
* depth: 2
title: List API Keys
url: '#list-api-keys'
* depth: 2
title: Create API Key
url: '#create-api-key'
* depth: 2
title: Get API Key
url: '#get-api-key'
* depth: 2
title: Delete API Key
url: '#delete-api-key'
* depth: 2
title: Update API Key
url: '#update-api-key'
* depth: 2
title: Create Full Agent
url: '#create-full-agent'
* depth: 2
title: Get Full Agent
url: '#get-full-agent'
* depth: 2
title: Delete Full Agent
url: '#delete-full-agent'
* depth: 2
title: Update Full Agent
url: '#update-full-agent'
* depth: 2
title: Create Full Project
url: '#create-full-project'
* depth: 2
title: Get Full Project
url: '#get-full-project'
* depth: 2
title: Delete Full Project
url: '#delete-full-project'
* depth: 2
title: Update Full Project
url: '#update-full-project'
* depth: 2
title: Initiate OAuth login for MCP tool
url: '#initiate-oauth-login-for-mcp-tool'
* depth: 2
title: OAuth authorization callback
url: '#oauth-authorization-callback'
structuredData:
headings:
* content: List Projects
id: list-projects
* content: Create Project
id: create-project
* content: Get Project
id: get-project
* content: Update Project
id: update-project
* content: Delete Project
id: delete-project
* content: List SubAgents
id: list-subagents
* content: Create SubAgent
id: create-subagent
* content: Get SubAgent
id: get-subagent
* content: Delete SubAgent
id: delete-subagent
* content: Update SubAgent
id: update-subagent
* content: List Agent Relations
id: list-agent-relations
* content: Create Agent Relation
id: create-agent-relation
* content: Get Agent Relation
id: get-agent-relation
* content: Delete Agent Relation
id: delete-agent-relation
* content: Update Agent Relation
id: update-agent-relation
* content: List Agent Agent
id: list-agent-agent
* content: Create Agent Agent
id: create-agent-agent
* content: Get Agent Agent
id: get-agent-agent
* content: Delete Agent Agent
id: delete-agent-agent
* content: Update Agent Agent
id: update-agent-agent
* content: Get Related Agent Infos
id: get-related-agent-infos
* content: Get Full Agent Definition
id: get-full-agent-definition
* content: List SubAgent Tool Relations
id: list-subagent-tool-relations
* content: Create SubAgent Tool Relation
id: create-subagent-tool-relation
* content: Get SubAgent Tool Relation
id: get-subagent-tool-relation
* content: Delete SubAgent Tool Relation
id: delete-subagent-tool-relation
* content: Update SubAgent Tool Relation
id: update-subagent-tool-relation
* content: Get SubAgents for Tool
id: get-subagents-for-tool
* content: Get Artifact Components for Agent
id: get-artifact-components-for-agent
* content: Get Agents Using Artifact Component
id: get-agents-using-artifact-component
* content: Associate Artifact Component with Agent
id: associate-artifact-component-with-agent
* content: Remove Artifact Component from Agent
id: remove-artifact-component-from-agent
* content: Check if Artifact Component is Associated with Agent
id: check-if-artifact-component-is-associated-with-agent
* content: Get Data Components for Agent
id: get-data-components-for-agent
* content: Get Agents Using Data Component
id: get-agents-using-data-component
* content: Associate Data Component with Agent
id: associate-data-component-with-agent
* content: Remove Data Component from Agent
id: remove-data-component-from-agent
* content: Check if Data Component is Associated with Agent
id: check-if-data-component-is-associated-with-agent
* content: List Artifact Components
id: list-artifact-components
* content: Create Artifact Component
id: create-artifact-component
* content: Get Artifact Component
id: get-artifact-component
* content: Delete Artifact Component
id: delete-artifact-component
* content: Update Artifact Component
id: update-artifact-component
* content: List Context Configurations
id: list-context-configurations
* content: Create Context Configuration
id: create-context-configuration
* content: Get Context Configuration
id: get-context-configuration
* content: Delete Context Configuration
id: delete-context-configuration
* content: Update Context Configuration
id: update-context-configuration
* content: List Credentials
id: list-credentials
* content: Create Credential
id: create-credential
* content: Get Credential
id: get-credential
* content: Delete Credential
id: delete-credential
* content: Update Credential
id: update-credential
* content: List Data Components
id: list-data-components
* content: Create Data Component
id: create-data-component
* content: Get Data Component
id: get-data-component
* content: Delete Data Component
id: delete-data-component
* content: Update Data Component
id: update-data-component
* content: List External Agents
id: list-external-agents
* content: Create External Agent
id: create-external-agent
* content: Get External Agent
id: get-external-agent
* content: Delete External Agent
id: delete-external-agent
* content: Update External Agent
id: update-external-agent
* content: List Function Tools
id: list-function-tools
* content: Create Function Tool
id: create-function-tool
* content: Get Function Tool by ID
id: get-function-tool-by-id
* content: Delete Function Tool
id: delete-function-tool
* content: Update Function Tool
id: update-function-tool
* content: List Functions
id: list-functions
* content: Create Function
id: create-function
* content: Get Function by ID
id: get-function-by-id
* content: Delete Function
id: delete-function
* content: Update Function
id: update-function
* content: List Tools
id: list-tools
* content: Create Tool
id: create-tool
* content: Get Tool
id: get-tool
* content: Delete Tool
id: delete-tool
* content: Update Tool
id: update-tool
* content: List API Keys
id: list-api-keys
* content: Create API Key
id: create-api-key
* content: Get API Key
id: get-api-key
* content: Delete API Key
id: delete-api-key
* content: Update API Key
id: update-api-key
* content: Create Full Agent
id: create-full-agent
* content: Get Full Agent
id: get-full-agent
* content: Delete Full Agent
id: delete-full-agent
* content: Update Full Agent
id: update-full-agent
* content: Create Full Project
id: create-full-project
* content: Get Full Project
id: get-full-project
* content: Delete Full Project
id: delete-full-project
* content: Update Full Project
id: update-full-project
* content: Initiate OAuth login for MCP tool
id: initiate-oauth-login-for-mcp-tool
* content: OAuth authorization callback
id: oauth-authorization-callback
contents:
* content: Check if the management service is healthy
* content: List all projects within a tenant with pagination
heading: list-projects
* content: Create a new project
heading: create-project
* content: Get a single project by ID
heading: get-project
* content: Update an existing project
heading: update-project
* content: Delete a project. Will fail if the project has existing resources.
heading: delete-project
* content: List all API keys for a tenant with optional pagination
heading: list-api-keys
* content: >-
Create a new API key for an agent. Returns the full key (shown only
once).
heading: create-api-key
* content: Get a specific API key by ID (does not return the actual key)
heading: get-api-key
* content: Delete an API key permanently
heading: delete-api-key
* content: Update an API key (currently only expiration date can be changed)
heading: update-api-key
* content: >-
Create a complete agent with all agents, tools, and relationships from
JSON definition
heading: create-full-agent
* content: >-
Retrieve a complete agent definition with all agents, tools, and
relationships
heading: get-full-agent
* content: >-
Delete a complete agent and cascade to all related entities
(relationships, not other agents/tools)
heading: delete-full-agent
* content: >-
Update or create a complete agent with all agents, tools, and
relationships from JSON definition
heading: update-full-agent
* content: >-
Create a complete project with all Agents, Sub Agents, tools, and
relationships from JSON definition
heading: create-full-project
* content: >-
Retrieve a complete project definition with all Agents, Sub Agents,
tools, and relationships
heading: get-full-project
* content: >-
Delete a complete project and cascade to all related entities (Agents,
Sub Agents, tools, relationships)
heading: delete-full-project
* content: >-
Update or create a complete project with all Agents, Sub Agents,
tools, and relationships from JSON definition
heading: update-full-project
* content: >-
Detects OAuth requirements and redirects to authorization server
(public endpoint)
heading: initiate-oauth-login-for-mcp-tool
* content: >-
Handles OAuth authorization codes and completes the authentication
flow
heading: oauth-authorization-callback
icon: LuDatabaseZap
***
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
REST API for the management of the Inkeep Agent Framework.
# Join & Follow
URL: /community/inkeep-community
undefined
***
title: Join & Follow
icon: "LuUsers"
---------------
To get help, share ideas, and provide feedback, join our community:
Get support, share ideas, and connect with other builders.
You can also find us on:
Updates, tips, and shout‑outs for builders.
Star the repo, open issues, and contribute.
Practical demos, tutorials, and deep dives.
Company updates, launches, and hiring news.
Feel free to tag us as `@inkeep` on 𝕏 or `@Inkeep` on LinkedIn with a video of what you're building — we like to highlight neat Agent use cases from the community where possible. Also feel free to submit a PR to our [template library](https://github.com/inkeep/agents/tree/main/agents-cookbook/template-projects).
To keep up to date with all news related to AI Agents, sign up for the Agents Newsletter:
Get the latest AI Agents news, tips, and updates delivered to your inbox.
# License
URL: /community/license
License for the Inkeep Agent Framework
***
title: License
description: License for the Inkeep Agent Framework
icon: "LuFileText"
------------------
The Inkeep Agent Framework is licensed under the **Elastic License 2.0** ([ELv2](https://www.elastic.co/licensing/elastic-license)) subject to **Inkeep's Supplemental Terms** ([SUPPLEMENTAL\_TERMS.md](https://github.com/inkeep/agents/blob/main/SUPPLEMENTAL_TERMS.md)). This is a [fair-code](https://faircode.io/), source-available license that allows broad usage while protecting against certain competitive uses.
# Connect Your Data with Context7
URL: /connect-your-data/context7
Learn how to connect your code repositories and documentation to your agents using Context7
***
title: Connect Your Data with Context7
sidebarTitle: Context7
description: Learn how to connect your code repositories and documentation to your agents using Context7
icon: "brand/Upstash"
keywords: Context7, GitHub, GitLab, BitBucket, code documentation, OpenAPI, MCP server, library documentation, code repositories, technical documentation
---------------------------------------------------------------------------------------------------------------------------------------------------------
Context7 specializes in connecting code repositories and technical documentation to your agents. It's particularly well-suited for developers who want their agents to have access to library documentation, API specs, and code repositories.
## Supported data sources
With Context7 you can connect:
* **Code Repositories**: GitHub Repositories, GitLab, BitBucket
* **API Documentation**: OpenAPI Spec
* **Documentation Formats**: LLMs.txt
* **Websites**: Website crawling and indexing
## Getting started
### Step 1: Check if your library is already available
Context7 maintains a library of pre-indexed documentation for popular libraries and frameworks. Before creating an account, check if your library is already available:
Visit [context7.com](https://context7.com/) and browse the list of available libraries. If your library is listed, you can use it immediately without additional setup.
If your library is already available in Context7's library, you can skip directly to Step 4 to get the library ID and register the MCP server.
### Step 2: Create an account
If your library isn't listed or you want to connect custom sources:
1. [Sign up for Context7](https://context7.com/sign-in)
2. Complete the account setup process
3. Verify your email address if required
### Step 3: Connect your data sources
1. Log in to your Context7 dashboard
2. Add your repositories, websites, or OpenAPI specs
3. Wait for Context7 to index your content
4. Verify that your content is accessible
### Step 4: Get the Context7 Library ID
To use a specific library with your agents, you'll need the Context7 Library ID. You can find this ID in the library's URL on context7.com.
**How to find the Library ID:**
1. Navigate to the library page on context7.com (e.g., `https://context7.com/supabase/supabase`)
2. Copy the path after the domain name
3. The Library ID is the path portion of the URL
**Example:**
* URL: `https://context7.com/supabase/supabase`
* Library ID: `supabase/supabase`
If you don't know the library ID, the Context7 MCP server can automatically match libraries based on your query using the `resolve-library-id` tool. See the "Automatic library matching" section below for details.
### Step 5: Register the MCP server
Register the Context7 MCP server as a tool in your agent configuration:
**Using TypeScript SDK:**
```typescript
import { mcpTool, subAgent } from "@inkeep/agents-sdk";
const context7Tool = mcpTool({
id: "context7-docs",
name: "context7_search",
description: "Search code documentation and library references",
serverUrl: "https://mcp.context7.com/mcp",
});
const devAgent = subAgent({
id: "dev-agent",
name: "Developer Assistant",
description: "Helps with code questions using library documentation",
prompt: `You are a developer assistant with access to code documentation.`,
canUse: () => [context7Tool],
});
```
**Using Visual Builder:**
1. Go to the **MCP Servers** tab in the Visual Builder
2. Click "New MCP server"
3. Enter:
* **Name**: `Context7 Documentation`
* **URL**: `https://mcp.context7.com/mcp`
* **Transport Type**: `Streamable HTTP` or `SSE`
4. Save the server
5. Add it to your agent by dragging it onto your agent canvas
### Step 6: Use the Context7 MCP server in your agent
Once your Context7 MCP server is registered, you can use it with a specific library ID (from Step 4) or let it automatically match libraries based on your query.
#### Specifying a library ID
If you know which library you want to use, specify its Context7 Library ID in your agent's prompt. This allows the Context7 MCP server to skip the library-matching step and directly retrieve documentation.
**Example:**
```typescript
const devAgent = subAgent({
id: "react-agent",
name: "React Assistant",
description: "Helps with React development",
prompt: `You are a React development assistant. Use library ID "websites/inkeep"
when searching for documentation. Use the get_library_docs tool to find React
documentation and examples.`,
canUse: () => [context7Tool],
});
```
#### Automatic library matching
If you don't specify a library ID, the Context7 MCP server will automatically match libraries based on your query. The server uses the `resolve-library-id` tool to identify the appropriate library, then uses the `get_library_docs` tool to retrieve the relevant documentation.
This approach works well when:
* You're working with multiple libraries
* The library name is mentioned in the user's query
* You want the agent to dynamically select the most relevant library
# Connect Your Data with Inkeep
URL: /connect-your-data/inkeep
Learn how to connect your data sources to your agents using Inkeep's comprehensive knowledge base platform
***
title: Connect Your Data with Inkeep
sidebarTitle: Inkeep
description: Learn how to connect your data sources to your agents using Inkeep's comprehensive knowledge base platform
icon: "brand/Inkeep"
keywords: Inkeep, knowledge base, data sources, MCP server, documentation integration, website indexing
-------------------------------------------------------------------------------------------------------
Inkeep provides a comprehensive platform for connecting and managing your data sources. With support for 25+ data source types, Inkeep makes it easy to create a unified knowledge base that your agents can access.
## Supported data sources
Inkeep supports a wide variety of data sources:
* **Documentation**: OpenAPI Spec, Plain text
* **Collaboration**: Confluence, Notion, Slack, Discord, Discourse, Missive
* **Code Repositories**: GitHub
* **Cloud Storage**: Google Drive
* **Websites**: Website crawling and indexing
* **Video**: YouTube
* **Support Systems**:
* Freshdesk Tickets
* HelpScout Docs and Tickets
* Zendesk Knowledge Base, Tickets, and Help Center
* **Project Management**: Jira
## Getting started
### Step 1: Set up your Inkeep account
If you don't have an Inkeep account yet, you can:
* [Try Inkeep on your content](https://inkeep.com/demo) - Test Inkeep with your own content
* [Schedule a call](https://inkeep.com/schedule-demo) - Get personalized setup assistance
### Step 2: Connect your data sources
1. Log in to your Inkeep dashboard
2. Navigate to the "Sources" tab
3. Add and configure your desired data sources (websites, GitHub repos, Notion pages, etc.)
4. Wait for Inkeep to index your content
### Step 3: Get your MCP server URL
Once your data sources are connected and indexed, obtain your Inkeep MCP server URL from your Inkeep dashboard. This URL will be used to register the MCP server with your agents.
### Step 4: Register the MCP server
Register your Inkeep MCP server as a tool in your agent configuration:
**Using TypeScript SDK:**
```typescript
import { mcpTool, subAgent } from "@inkeep/agents-sdk";
const inkeepTool = mcpTool({
id: "inkeep-knowledge-base",
name: "knowledge_base",
description: "Search the company knowledge base powered by Inkeep",
serverUrl: "YOUR_INKEEP_MCP_SERVER_URL", // From your Inkeep dashboard
});
const supportAgent = subAgent({
id: "support-agent",
name: "Support Agent",
description: "Answers questions using the company knowledge base",
prompt: `You are a support agent with access to the company knowledge base.`,
canUse: () => [inkeepTool],
});
```
**Using Visual Builder:**
1. Go to the **MCP Servers** tab in the Visual Builder
2. Click "New MCP server"
3. Select "Custom Server"
4. Enter:
* **Name**: `Inkeep Knowledge Base`
* **URL**: Your Inkeep MCP server URL
* **Transport Type**: `Streamable HTTP`
5. Save the server
6. Add it to your agent by dragging it onto your agent canvas
# Connecting Your Data
URL: /connect-your-data/overview
Learn how to connect your data sources to your agents through MCP servers
***
title: Connecting Your Data
sidebarTitle: Overview
description: Learn how to connect your data sources to your agents through MCP servers
icon: "LuSparkles"
keywords: data sources, MCP servers, knowledge base, documentation, GitHub, website integration
-----------------------------------------------------------------------------------------------
Connect your data sources to your agents through MCP servers. Support websites, GitHub repositories, documentation, knowledge bases, PDFs, and more. Your agents can search and access this content in real-time.
## How it works
1. **Set up your data source** - Configure your chosen provider and connect your data sources
2. **Get your MCP server URL** - Obtain the MCP server endpoint from your provider
3. **Register the MCP server** - Add it as a tool in your agent configuration
4. **Use in your agents** - Your agents can now search and access your connected data
## Choose a data provider
Select a provider that supports your data sources:
Connect 25+ data sources including websites, GitHub, Notion, Slack, Confluence, and more. Comprehensive knowledge base solution.
Connect GitHub, GitLab, BitBucket repositories, OpenAPI specs, and websites. Great for code documentation.
Connect GitHub repositories, PDFs, and Markdown files. Simple and focused solution for documentation.
## Other options
We recommend Inkeep, Context7, or Ref for the easiest setup—they handle MCP server management automatically.
For more advanced use cases, you can use [Reducto](https://reducto.ai/) or [Unstructured](https://unstructured.io/). Both offer self-serve free tiers and allow you to upload documents and access them via their APIs or SDKs. You can either wrap these in your own MCP server or invoke them directly using [function tools](/typescript-sdk/tools/function-tools).
# Connect Your Data with Ref
URL: /connect-your-data/ref
Learn how to connect your documentation and code repositories to your agents using Ref
***
title: Connect Your Data with Ref
sidebarTitle: Ref
description: Learn how to connect your documentation and code repositories to your agents using Ref
icon: "brand/Ref"
keywords: Ref, GitHub, PDF, Markdown, documentation, MCP server, knowledge base, API key
----------------------------------------------------------------------------------------
Ref provides a simple and focused solution for connecting your documentation and code repositories to your agents. With support for GitHub repositories, PDFs, and Markdown files, Ref is perfect for teams that need straightforward documentation access.
## Supported data sources
With Ref you can connect:
* **Code Repositories**: GitHub Repositories
* **Documents**: PDF files
* **Documentation**: Markdown files
## Getting started
### Step 1: Create an account
1. [Sign up for Ref](https://ref.tools/login)
2. Complete the account registration process
### Step 2: Upload your resources
1. Log in to your Ref dashboard
2. Navigate to the [Resources page](https://ref.tools/resources)
3. Upload your PDFs, Markdown files, or connect your GitHub repositories
4. Wait for Ref to process and index your content
### Step 3: Get your MCP server URL
1. Navigate to the [Install MCP page](https://ref.tools/install)
2. Copy the MCP server URL (it will start with `https://api.ref.tools/mcp?apiKey=ref-`)
### Step 4: Register the MCP server
Register the Ref MCP server as a tool in your agent configuration. Replace `` with your actual API key from Step 3.
**Using TypeScript SDK:**
```typescript
import { mcpTool, subAgent } from "@inkeep/agents-sdk";
const refTool = mcpTool({
id: "ref-documentation",
name: "ref_search",
description: "Search uploaded documentation and code repositories",
serverUrl: "https://api.ref.tools/mcp?apiKey=ref-",
});
const docAgent = subAgent({
id: "doc-agent",
name: "Documentation Assistant",
description: "Answers questions using uploaded documentation",
prompt: `You are a documentation assistant with access to company documentation`,
canUse: () => [refTool],
});
```
**Using Visual Builder:**
1. Go to the **MCP Servers** tab in the Visual Builder
2. Click "New MCP server"
3. Select "Custom Server"
4. Enter:
* **Name**: `Ref Documentation`
* **URL**: `https://api.ref.tools/mcp?apiKey=ref-` (replace with your API key)
* **Transport Type**: `Streamable HTTP`
5. Save the server
6. Add it to your agent by dragging it onto your agent canvas
# Push / Pull
URL: /get-started/push-pull
Push and pull your agents to and from the Visual Builder
***
title: Push / Pull
description: Push and pull your agents to and from the Visual Builder
icon: "LuArrowLeftRight"
------------------------
## Push code to visual
With Inkeep, you can define your agents in code, push them to the Visual Builder, and continue developing with the intuitive drag-and-drop interface. You can switch back to code any time.
Let's walk through the process.
### Step 1: Install the Inkeep CLI
```bash
pnpm install -g @inkeep/agents-cli
```
### Step 2: Download a template project
Navigate to the `src/projects` directory.
```bash
cd src/projects
```
Add the docs assistant agent using `inkeep add`.
```bash
inkeep add --project docs-assistant
```
Find the downloaded code in `src/projects/docs-assistant`.
`inkeep add` imports a template project from our [cookbook library](https://github.com/inkeep/agents/tree/main/agents-cookbook/template-projects).
### Step 3: Push code to visual
Navigate to your docs assistant project.
```bash
cd docs-assistant
```
Use `inkeep push` to push the code to the Visual Builder.
```bash
inkeep push
```
To validate your project without pushing, use the `--json` flag: `inkeep push --json`
### Step 4: Chat with your agent
Refresh [http://localhost:3000](http://localhost:3000), switch to the **Docs Assistant** project (in the bottom left).
Under **Agents**, click on the Docs Assistant agent and press **Try it**. Ask a question about Inkeep.
## Run `inkeep pull`
Make some changes, like changing a prompt, and let's walk through `inkeep pull`.
<>
### Prerequisite
The `inkeep pull` command in-part leverages AI to sync your TypeScript files to the state of your Visual Builder, so **at least one** of the below environment variables to be defined:
```txt .env
# Choose one:
ANTHROPIC_API_KEY=your_api_key_here
# or
OPENAI_API_KEY=your_api_key_here
# or
GOOGLE_API_KEY=your_api_key_here
```
The CLI prioritizes Anthropic → OpenAI → Google.
Here are the models used:
| Provider | Model(s) | Where to Get API Key |
| --------- | ------------------------------------- | --------------------------------------------------- |
| Anthropic | Claude Sonnet 4.5 (extended thinking) | [Anthropic Console](https://console.anthropic.com/) |
| OpenAI | GPT-5.1 | [OpenAI Platform](https://platform.openai.com/) |
| Google | Gemini 2.5 Flash | [Google AI Studio](https://ai.google.dev/) |
>
### Step 1: Make an edit visually
Make an edit to the docs assistant agent in the UI, such as changing the prompt of the agent.
### Step 2: Pull code from visual
Navigate to your docs assistant project.
```bash
cd src/projects/docs-assistant
```
Use `inkeep pull` to pull the code from the Visual Builder to your local project.
```bash
inkeep pull
```
### Step 3: Verify the code was pulled
Check the `src/projects/docs-assistant/agents/docs-assistant.ts` file for the updated prompt.
```bash
cat src/projects/docs-assistant/agents/docs-assistant.ts
```
## Next steps
Next, we recommend setting up observability to see live traces of your agent. See [Traces](/get-started/traces) to get started.
Set up SigNoz to enable live debugging capabilities for your agents
# Quick Start
URL: /get-started/quick-start
Get started with Inkeep Agents in <1min
***
title: Quick Start
description: Get started with Inkeep Agents in \<1min
icon: "LuRocket"
----------------
## Launch your first agent
### Prerequisites
Before getting started, ensure you have the following installed on your system:
* [Node.js](https://nodejs.org/en/download/) version 22 or higher
* [Docker](https://docs.docker.com/get-docker/)
* [pnpm](https://pnpm.io/installation) version 10 or higher
You can verify by running:
```bash
node --version
pnpm --version
docker --version
```
### Step 1: Create a new agents project
Run the quickstart script on a target folder:
```bash
npx @inkeep/create-agents my-agents
```
Navigate to the folder
```bash
cd my-agents
```
Open the folder using your favorite coding editor. To open with Cursor, you can run `cursor .`
### Step 2: Run the setup script
Ensure Docker Desktop (or Docker daemon) is running before running the setup script.
```bash
pnpm setup-dev
```
Or if you are using a cloud database, you can skip the docker database startup by running:
```bash
pnpm setup-dev --skip-docker
```
Make sure your DATABASE\_URL environment variable is configured for your cloud database.
### Step 3: Launch the dev environment
```bash
pnpm dev
```
The Visual Builder will auto-open at [http://localhost:3000](http://localhost:3000).
### Step 4: Chat with your agent
Navigate to the **Activities Planner** agent at [http://localhost:3000](http://localhost:3000), click **Try it**, and ask about fun activities at a location of your choice:
### Step 5: Install Inkeep MCP (optional)
To help "vibe code" agents with Inkeep, add the `Inkeep Agents MCP` to your preferred IDE.
To add to **Claude Code**, run this in your terminal:
```bash
claude mcp add --transport http inkeep-agents https://agents.inkeep.com/mcp --scope project
```
Or manually add `https://agents.inkeep.com/mcp` as an MCP Server to any MCP client.
### Next steps
Next, we recommend learning about `inkeep push` and `inkeep pull` so you can go from `SDK -> Visual Builder` and `Visual Builder -> SDK`. See the [Push / Pull](/get-started/push-pull) guide for a quick example.
Use our cookbook to learn about push and pull.
# Live Debugger, Traces, and OTEL Telemetry
URL: /get-started/traces
Set up SigNoz to enable full observability with traces and live debugging capabilities for your agents.
***
title: Live Debugger, Traces, and OTEL Telemetry
sidebarTitle: Traces
description: Set up SigNoz to enable full observability with traces and live debugging capabilities for your agents.
icon: "LuActivity"
keywords: SigNoz, traces, live debugger, observability, OpenTelemetry, monitoring, distributed tracing, debugging, copy trace, export trace, JSON export
--------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview
The Inkeep Agent Framework provides powerful **traces** and **live debugging** capabilities powered by SigNoz. Setting up SigNoz gives you:
* **Real-time trace visualization** - See exactly how your agents execute step-by-step
* **Live debugging** - Debug agent conversations as they happen
* **Export traces as JSON** - Copy complete traces for offline analysis and debugging
* **Full observability** - Complete OpenTelemetry instrumentation for monitoring
* **Performance insights** - Identify bottlenecks and optimize agent performance
## Setup Options
You can set up SigNoz in two ways:
1. **Cloud Setup**: Use SigNoz Cloud
2. **Local Setup**: Run SigNoz locally using Docker
## Option 1: SigNoz Cloud Setup
### Step 1: Create a SigNoz Cloud Project
1. Sign up at [SigNoz](https://signoz.io/teams/)
2. Create a new project or use an existing one
### Step 2: Save Your SigNoz Credentials
You'll need to collect three pieces of information from your SigNoz dashboard:
1. **API Key**:
* Navigate to Settings → Workspace Settings → API Keys → New Key
* Choose any role (Admin, Editor, or Viewer) - Viewer is sufficient for observability
* Set the expiration field to "No Expiry" to prevent the key from expiring
* Copy the generated API key
2. **Ingestion Key**:
* Navigate to Settings → Workspace Settings → Ingestion
* Set the expiration field to "No Expiry" to prevent the key from expiring
* Copy the ingestion key
3. **SigNoz URL**:
* Copy the URL from your browser's address bar
* It will look like: `https://.signoz.cloud`
### Step 3: Configure Your Root `.env` File
```bash
# SigNoz
SIGNOZ_URL=https://.signoz.cloud
SIGNOZ_API_KEY=
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://ingest.us.signoz.cloud:443/v1/traces
OTEL_EXPORTER_OTLP_TRACES_HEADERS="signoz-ingestion-key="
```
### Step 4: Verify Cloud Setup
1. Restart your development environment:
```bash
pnpm dev
```
2. Generate some traces by interacting with your agents
3. Open your SigNoz cloud dashboard and navigate to "Traces" to see your agent traces
## Option 2: Local SigNoz Setup
### Prerequisites
* Docker installed on your machine
### Step 1: Clone the Optional Services Repository
Clone the Inkeep optional local development services repository:
```bash
git clone https://github.com/inkeep/agents-optional-local-dev
cd agents-optional-local-dev
```
### Step 2: Start SigNoz Services
Run the following command to start SigNoz and related services:
```bash
docker-compose --profile signoz up -d
```
This will start:
* SigNoz frontend (accessible at `http://localhost:3080`)
* SigNoz query service
* SigNoz OTEL collector
* ClickHouse database
When you visit `http://localhost:3080`, you can sign up with your desired credentials.
### Step 3: Configure Environment Variables
In your **root project directory** (e.g., `my-agents`), update your `.env` file:
```bash
# SigNoz Configuration
SIGNOZ_URL=http://localhost:3080
SIGNOZ_API_KEY=your-signoz-api-key
# IMPORTANT: Comment out the OTEL Configuration
# OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://ingest.us.signoz.cloud:443/v1/traces
# OTEL_EXPORTER_OTLP_TRACES_HEADERS="signoz-ingestion-key="
```
To get your SigNoz API key:
1. Open SigNoz at `http://localhost:3080`
2. Navigate to Settings → Account Settings → API Keys → New Key
3. Create a new API key or copy an existing one.
* Choose any role (Admin, Editor, or Viewer) - Viewer is sufficient for observability
* Set the expiration field to "No Expiry" to prevent the key from expiring
### Step 4: Verify Setup
1. Restart your Inkeep agents:
```bash
pnpm dev
```
2. Make some requests to your agents to generate traces
3. Open SigNoz at `http://localhost:3080` and navigate to the "Traces" section to see your agent traces
## Viewing Traces and Using the Live Debugger
Once SigNoz is set up, you can access traces and live debugging in two ways:
### 1. Visual Builder Traces Interface
If you're using the Visual Builder:
1. Open your agent project in the Visual Builder
2. Navigate to the **Traces** section
3. You'll see real-time traces of your agent executions
4. Click on any trace to see detailed execution flow and timing
The traces overview shows conversation metrics and recent activity:
Click on any conversation to see detailed execution flow:
<>
### Copy Trace for Debugging
The `Copy Trace` button in the timeline view allows you to export the entire conversation trace as JSON. This is particularly useful for offline analysis and debugging complex flows.
#### What's Included in the Trace Export
When you click `Copy Trace`, the system exports a JSON object containing:
```json
{
"metadata": {
"conversationId": "unique-conversation-id",
"traceId": "distributed-trace-id",
"agentId": "agent-identifier",
"agentName": "Agent Name",
"exportedAt": "2025-10-14T12:00:00.000Z"
},
"timing": {
"startTime": "2025-10-14T11:59:00.000Z",
"endTime": "2025-10-14T12:00:00.000Z",
"durationMs": 60000
},
"timeline": [
// Array of all activities with complete details:
// - Agent messages and responses
// - Tool calls and results
// - Agent transfers
// - Artifact information
// - Execution context
]
}
```
#### How to Use Copy Trace
1. Navigate to the **Traces** section in the management UI
2. Open the conversation you want to debug
3. Click the **Copy Trace** button at the top of the timeline
4. The complete trace JSON is copied to your clipboard
5. Paste it into your preferred tool for analysis
This exported trace contains all the activities shown in the timeline, making it easy to share complete execution context with team members or support.
>
### 2. SigNoz Dashboard
For detailed analysis and further debugging:
1. Open your SigNoz dashboard (cloud or local)
2. Navigate to **Traces** to see all agent executions
3. Use filters to find specific conversations or agents
4. Click on traces to see:
* Step-by-step execution details
* Performance metrics
* Error information
* Agent-to-agent communication flows
For more detailed information on using traces, see the [SigNoz Usage guide](/typescript-sdk/signoz-usage).
## Additional Observability and Evals
👉 For additional observability or a dedicated Evals platform, you can connect to any OTEL-based provider. For example, check out the [Langfuse Usage guide](/typescript-sdk/langfuse-usage) for end-to-end instructions.
## Next steps
Next, we recommend setting up the Nango credential store for production-ready credential management. See [Credentials](/typescript-sdk/credentials/overview) to get started.
# Quick Start
URL: /quick-start/start-development
Start developing your agents with the Inkeep Agent Platform
***
title: Quick Start
description: Start developing your agents with the Inkeep Agent Platform
icon: "LuRocket"
----------------
### Prerequisites
* Node.js 22+
* Docker (installation instructions [here](https://docs.docker.com/engine/install))
* pnpm 10+ (installation instructions [here](https://pnpm.io/installation))
### Step 1: Create a new agents project
```bash
npx @inkeep/create-agents my-agents
cd my-agents
```
### Step 2: Run the setup script
```bash
pnpm setup-dev
```
### Step 3: Launch the development environment
```bash
pnpm dev
```
The Visual Builder will open automatically at [http://localhost:3000](http://localhost:3000).
#### Service Ports
The development environment starts multiple services on different ports:
| Service | Port | URL | Description |
| ------------------ | ---- | ---------------------------------------------- | ------------------------------------------------------ |
| **Visual Builder** | 3000 | [http://localhost:3000](http://localhost:3000) | Web interface for building and managing agents |
| **Manage API** | 3002 | [http://localhost:3002](http://localhost:3002) | API for managing agent configurations and projects |
| **Run API** | 3003 | [http://localhost:3003](http://localhost:3003) | API for executing agent conversations with your agents |
Make sure these ports are available before starting the development environment. If any port is in use, you'll need to free it up first.
### Step 3: Install the Inkeep CLI
```bash
npm install -g @inkeep/agents-cli
```
### Step 4: Push your project
Running this command will push the code you defined your agents and tools with to the Visual Builder.
```bash
cd src/weather-project
inkeep push
```
### Step 5: Chat with your agent
Open the Visual Builder at [http://localhost:3000](http://localhost:3000), click into the weather graph, and then click the "Try It" button to start chatting with the agent.
Next, we recommend setting up observability to see live traces of your agent. See [Traces](/quick-start/traces) for more information.
# Deploy to AWS EC2
URL: /self-hosting/aws-ec2
Deploy to AWS EC2 with Docker Compose
***
title: Deploy to AWS EC2
sidebarTitle: AWS EC2
description: Deploy to AWS EC2 with Docker Compose
icon: "LuServerCog"
-------------------
## Create a VM Instance
* Go to [Compute Engine](https://console.aws.amazon.com/ec2/v2/home).
* Launch an instance
* Select Amazon Machine Image (AMI)
* Recommended size is at least `t2.large` (2 vCPU, 8 GiB Memory).
* Click "Edit" in the "Network settings" section. Set up an Inbound Security Group Rules for (TCP, 3000, 0.0.0.0/0), (TCP, 3002-3003, 0.0.0.0/0), (TCP, 3050-3051, 0.0.0.0/0), and (TCP, 3080, 0.0.0.0/0). These are the ports exposed by the Inkeep services.
* Auto-assign public IP
* Increase the size of storage to 30 GiB.
## Install Docker Compose
1. SSH into the EC2 Instance
2. Install packages
```bash
sudo dnf update
sudo dnf install -y git
sudo dnf install -y docker
```
```bash
sudo mkdir -p /usr/libexec/docker/cli-plugins
sudo curl -SL https://github.com/docker/compose/releases/latest/download/docker-compose-linux-$(uname -m) -o /usr/libexec/docker/cli-plugins/docker-compose
sudo chmod +x /usr/libexec/docker/cli-plugins/docker-compose
```
## Deploy SigNoz and Nango
Clone this repo, which includes Docker files with SigNoz and Nango:
```bash
git clone https://github.com/inkeep/agents-optional-local-dev inkeep-external-services
cd inkeep-external-services
```
Run this command to autogenerate a `.env` file:
```bash
cp .env.example .env && \
encryption_key=$(openssl rand -base64 32) && \
tmp_file=$(mktemp) && \
sed "s||$encryption_key|" .env > "$tmp_file" && \
mv "$tmp_file" .env && \
echo "Docker environment file created with auto-generated encryption key"
```
Nango requires a `NANGO_ENCRYPTION_KEY`. Once you create this, it cannot be edited.
Here's an overview of the important environment variables when deploying to production. Make sure to replace all of these in the `.env` file.
```bash
NANGO_ENCRYPTION_KEY=
# Replace these with your in production!
NANGO_SERVER_URL=http://:3050
NANGO_PUBLIC_CONNECT_URL=http://:3051
# Modify these in production environments!
NANGO_DASHBOARD_USERNAME=admin@example.com
NANGO_DASHBOARD_PASSWORD=adminADMIN!@12
```
Build and deploy SigNoz, Nango, OTEL Collector, and Jaeger:
```bash
docker compose up -d
```
This may take up to 5 minutes to start.
### Retrieve your SigNoz and Nango API Keys
To get your SigNoz API key `SIGNOZ_API_KEY`:
* Open SigNoz in a browser at `http://:3080`
* Navigate to Settings → Account Settings → API Keys → New Key
* Choose a role, Viewer is sufficient for observability
* Set the expiration field to "No Expiry" to prevent the key from expiring
To get your Nango secret key `NANGO_SECRET_KEY`:
* Open Nango in a browser at `http://:3050`
* Nango auto-creates two environments, Prod and Dev. Select the one you will use.
* Navigate to Environment Settings to find the secret key
## Deploy the Inkeep Agent Framework
From the root directory, create a new project directory for the Docker Compose setup for the Inkeep Agent Framework
```bash
mkdir inkeep && cd inkeep
wget https://raw.githubusercontent.com/inkeep/agents/refs/heads/main/docker-compose.yml
wget https://raw.githubusercontent.com/inkeep/agents/refs/heads/main/.env.docker.example
```
Generate a `.env` file from the example:
```bash
cp .env.docker.example .env
```
Here's an overview of the important environment variables when deploying to production. Make sure to replace all of these in the `.env` file.
```bash
# Change to "production" if deploying to production
ENVIRONMENT=production
# AI Provider Keys (you need at least one)
ANTHROPIC_API_KEY=
OPENAI_API_KEY=
GOOGLE_GENERATIVE_AI_API_KEY=
# Nango
NANGO_SECRET_KEY=
# SigNoz
SIGNOZ_API_KEY=
# Uncomment and set each of these with (openssl rand -hex 32)
INKEEP_AGENTS_MANAGE_API_BYPASS_SECRET=
INKEEP_AGENTS_RUN_API_BYPASS_SECRET=
INKEEP_AGENTS_JWT_SIGNING_SECRET=
# Uncomment and set these for the Manage UI at http://:3000
PUBLIC_INKEEP_AGENTS_MANAGE_API_URL=http://:3002
PUBLIC_INKEEP_AGENTS_RUN_API_URL=http://:3003
PUBLIC_INKEEP_AGENTS_RUN_API_BYPASS_SECRET=
PUBLIC_NANGO_SERVER_URL=http://:3050
PUBLIC_NANGO_CONNECT_BASE_URL=http://:3051
PUBLIC_SIGNOZ_URL=http://:3080
# Uncomment and set these to access Manage UI at http://:3000
INKEEP_AGENTS_MANAGE_UI_USERNAME=admin@example.com
INKEEP_AGENTS_MANAGE_UI_PASSWORD=adminADMIN!@12
```
<>
:::tip Advanced Configuration
For long-running agents or custom deployment requirements, you can override runtime limits like execution timeouts, maximum transfers, and generation steps. See [Configure Runtime Limits](/docs/self-hosting/configure-runtime-limits) for examples and the complete list of overridable settings.
:::
>
Run with Docker:
```bash
docker compose up -d
```
Then open `http://:3000` in a browser!
# Configure Runtime Limits
URL: /self-hosting/configure-runtime-limits
Customize execution limits, timeouts, and constraints for your deployment
***
title: Configure Runtime Limits
description: Customize execution limits, timeouts, and constraints for your deployment
icon: "LuSettings2"
-------------------
# Configure Runtime Limits
## Overview
The Inkeep Agent Framework includes sensible defaults for execution limits, timeouts, and constraints. However, certain use cases—like long-running orchestration agents—may require different configurations.
## How Runtime Configuration Works
### Two Types of Limits
**1. API-Configurable Limits** (set per agent/sub-agent via manage-api)
* Configured in your agent definitions using `stopWhen`
* Controls agent-specific behavior
* See [Agent Settings - StopWhen](/docs/typescript-sdk/agent-settings#configuring-stopwhen)
**2. Runtime Environment Limits** (set via environment variables)
* System-wide defaults and maximum allowed values
* Controls infrastructure-level constraints
* Documented in this guide
### Configuration Hierarchy
When an agent executes:
1. Uses agent-specific `stopWhen` settings if configured
2. Falls back to runtime environment defaults
3. Cannot exceed runtime environment maximums
### Understanding the Constants Architecture
The runtime environment limits are defined as TypeScript constants in the `@inkeep/agents-core` package. These constants are organized into two categories based on their purpose:
**1. Schema Validation Constants** (`packages/agents-core/src/constants/schema-validation/defaults.ts`)
* Define **API-level validation limits** (min, max, default values)
* Control what values users can configure via the manage-api
* Used in Zod schemas to validate agent configuration requests
* Examples: Transfer count limits, generation step limits, prompt character limits
**2. Runtime Execution Constants - Shared** (`packages/agents-core/src/constants/execution-limits-shared/defaults.ts`)
* Define **internal runtime behavior** limits
* Control infrastructure-level timeouts, retries, and constraints
* Shared across both manage-api and run-api services
* Examples: MCP connection timeouts, conversation history token limits
**3. Runtime Execution Constants - Run-API** (`packages/agents-run-api/src/constants/execution-limits/defaults.ts`)
* Define **run-api specific runtime behavior** limits
* Control execution engine timeouts, retries, and resource constraints
* Only used by the run-api service (not shared with manage-api)
* Examples: LLM generation timeouts, function tool sandbox limits, streaming buffer sizes
Each constant includes detailed inline documentation explaining its purpose, behavior, and impact on the runtime. **The TypeScript constant files are the source of truth** for default values and available overrides—not `.env.example`.
All constants can be overridden via environment variables prefixed with `AGENTS_`. For example:
```bash
# Override a schema validation constant
AGENTS_AGENT_EXECUTION_TRANSFER_COUNT_DEFAULT=50
# Override a runtime execution constant
AGENTS_MCP_TOOL_CONNECTION_TIMEOUT_MS=5000
```
## Use Case: Long-Running Orchestration Agents
For agents that orchestrate complex workflows (like coding agents that run for hours), you'll want to increase various limits and timeouts.
### Recommended Configuration
Add these to your `.env` file:
```bash
# Agent Execution - Allow more sub-agent transfers for complex orchestration
AGENTS_EXECUTION_TRANSFER_COUNT_DEFAULT=50 # Default: 10
AGENTS_EXECUTION_TRANSFER_COUNT_MAX=2000 # Default: 1000
# Sub-Agent Turns - Allow more LLM generation steps per turn
AGENTS_SUB_AGENT_TURN_GENERATION_STEPS_DEFAULT=30 # Default: 12
AGENTS_SUB_AGENT_TURN_GENERATION_STEPS_MAX=2000 # Default: 1000
# LLM Timeouts - Increase for longer-running operations
AGENTS_LLM_GENERATION_FIRST_CALL_TIMEOUT_MS_STREAMING=600000 # 10min, Default: 4.5min
AGENTS_LLM_GENERATION_SUBSEQUENT_CALL_TIMEOUT_MS=180000 # 3min, Default: 1.5min
# Function Tools - Allow longer execution for complex operations
AGENTS_FUNCTION_TOOL_EXECUTION_TIMEOUT_MS_DEFAULT=120000 # 2min, Default: 30sec
# MCP Tools - Increase timeout for external tool operations
AGENTS_MCP_TOOL_REQUEST_TIMEOUT_MS_DEFAULT=180000 # 3min, Default: 1min
# Session Management - Keep tool results cached longer
AGENTS_SESSION_TOOL_RESULT_CACHE_TIMEOUT_MS=1800000 # 30min, Default: 5min
# Streaming - Allow streams to run longer
AGENTS_STREAM_MAX_LIFETIME_MS=1800000 # 30min, Default: 10min
```
### Why These Settings?
* **Transfer Count**: Coding orchestration often involves many handoffs between specialist agents (planning → implementation → testing → refinement)
* **Generation Steps**: Each coding operation may require multiple tool calls (read files, analyze, write code, run tests)
* **Timeouts**: Code generation and analysis can take time, especially for large files or complex refactoring
* **Cache Duration**: Keeps tool results available throughout long sessions for artifact processing
## Setting Variables by Deployment Type
### Local Development (Docker Compose)
```bash
# Edit .env file
vim .env
# Add your overrides
AGENTS_EXECUTION_TRANSFER_COUNT_DEFAULT=50
# ... other settings
# Restart services
docker compose down && docker compose up -d
```
### Production Deployments
#### AWS EC2, GCP, Hetzner
Add variables to your `.env` file before running `docker compose up`:
```bash
cp .env.docker.example .env
# Edit .env with your overrides
vim .env
docker compose up -d
```
#### Vercel, Cloud Run, etc.
Set environment variables in your platform's environment configuration UI.
## All Available Configuration Variables
All runtime configuration variables are defined as TypeScript constants. To explore available overrides and their detailed documentation:
1. **View the constant files** (source of truth):
* Schema validation constants: `packages/agents-core/src/constants/schema-validation/defaults.ts`
* Runtime execution constants (shared): `packages/agents-core/src/constants/execution-limits-shared/defaults.ts`
* Runtime execution constants (run-api): `packages/agents-run-api/src/constants/execution-limits/defaults.ts`
2. Each constant includes inline documentation explaining its purpose, behavior, and impact
3. Convert constant names to environment variables by prefixing with `AGENTS_`
### Configuration Categories
The runtime configuration is organized into functional categories:
**Schema Validation Constants** (API-level limits):
* **Agent Execution Transfer Count**: Limits transfers between sub-agents in a turn
* **Sub-Agent Turn Generation Steps**: LLM generation steps within a single sub-agent activation
* **Status Update Thresholds**: Event and time-based triggers for status updates
* **Prompt Validation**: Character limits for agent and sub-agent system prompts
* **Context Fetchers**: HTTP timeouts for external data fetching (CRM lookups, API calls)
**Runtime Execution Constants - Shared** (infrastructure-level limits):
* **MCP Tool Connection & Retry**: Connection timeouts and exponential backoff for MCP tools
* **Conversation History**: Token limits for conversation context windows
**Runtime Execution Constants - Run-API** (run-api service-specific limits):
* **LLM Generation Timeouts**: Timeout behavior for AI model calls
* **Function Tool Sandbox**: Execution limits for function tools in isolated sandboxes
* **Delegation & A2A**: Inter-agent communication settings
* **Artifact Processing**: UI component generation with retry mechanisms
* **Session Management**: Tool result caching and cleanup
* **Streaming**: Frequency, batching, and lifetime limits for streams
## Related Documentation
* [Agent Settings - StopWhen](/docs/typescript-sdk/agent-settings#configuring-stopwhen) - Configure per-agent limits
* [Environment Configuration](/docs/community/contributing/environment-configuration) - Development environment setup
* [Configuration Management](/docs/typescript-sdk/configuration) - Workspace configuration
# Build a Custom Docker Image
URL: /self-hosting/docker-build
How to build your own Docker images
***
title: Build a Custom Docker Image
sidebarTitle: Custom Image
description: How to build your own Docker images
icon: "LuWrench"
----------------
If you created a project from the quick start, the template includes a set of Dockerfiles and `docker-compose.yml` files.
To build and run locally:
```
docker compose build
docker compose up -d
```
# Deploy using Docker (Local Development)
URL: /self-hosting/docker-local
undefined
***
title: Deploy using Docker (Local Development)
sidebarTitle: Local Development
icon: "LuLaptop"
----------------
## Install Docker
* [Install Docker Desktop](https://www.docker.com/products/docker-desktop/)
## Deploy SigNoz and Nango
For full functionality, the **Inkeep Agent Framework** requires [**SigNoz**](https://signoz.io/) and [**Nango**](https://www.nango.dev/). You can sign up for a cloud hosted account with them directly, or you can self host them. Follow these instructions to self-host both SigNoz and Nango.
Clone this repo, which includes docker files with SigNoz and Nango:
```bash
git clone https://github.com/inkeep/agents-optional-local-dev inkeep-external-services
cd inkeep-external-services
```
Run this command to autogenerate a `.env` file:
```bash
cp .env.example .env && \
encryption_key=$(openssl rand -base64 32) && \
tmp_file=$(mktemp) && \
sed "s||$encryption_key|" .env > "$tmp_file" && \
mv "$tmp_file" .env && \
echo "Docker environment file created with auto-generated encryption key"
```
Nango requires a `NANGO_ENCRYPTION_KEY`. Once you create this, it cannot be edited.
Build and deploy SigNoz, Nango, OTEL Collector, and Jaeger:
```bash
docker compose up -d
```
This may take up to 5 minutes to start.
### Retrieve your SigNoz and Nango API Keys
To get your SigNoz API key `SIGNOZ_API_KEY`:
* Open SigNoz in a browser at `http://localhost:3080`
* Navigate to Settings → Account Settings → API Keys → New Key
* Choose a role, Viewer is sufficient for observability
* Set the expiration field to "No Expiry" to prevent the key from expiring
To get your Nango secret key `NANGO_SECRET_KEY`:
* Open Nango in a browser at `http://localhost:3050`
* Nango autocreates two environments Prod and Dev, select the one you will use
* Navigate to Environment Settings to find the secret key
## Deploy the Inkeep Agent Framework
From the root directory, create a new project directory for the docker compose setup for Inkeep Agent Framework
```bash
mkdir inkeep && cd inkeep
wget https://raw.githubusercontent.com/inkeep/agents/refs/heads/main/docker-compose.yml
wget https://raw.githubusercontent.com/inkeep/agents/refs/heads/main/.env.docker.example
```
Generate a `.env` file from the example:
```bash
cp .env.docker.example .env
```
Here's an overview of the important environment variables when deploying. Make sure to replace all of these in the `.env` file.
```bash
ENVIRONMENT=development
# AI Provider Keys (you need at least one)
ANTHROPIC_API_KEY=
OPENAI_API_KEY=
GOOGLE_GENERATIVE_AI_API_KEY=
# Nango
NANGO_SECRET_KEY=
# SigNoz
SIGNOZ_API_KEY=
# Default username and password for Manage UI (http://localhost:3000)
# INKEEP_AGENTS_MANAGE_UI_USERNAME=admin@example.com
# INKEEP_AGENTS_MANAGE_UI_PASSWORD=adminADMIN!@12
```
<>
:::tip Advanced Configuration
For long-running agents or custom deployment requirements, you can override runtime limits like execution timeouts, maximum transfers, and generation steps. See [Configure Runtime Limits](/docs/self-hosting/configure-runtime-limits) for examples and the complete list of overridable settings.
:::
>
Run with docker:
```bash
docker compose up -d
```
Then open [http://localhost:3000](http://localhost:3000) in a browser!
* Manage UI ([http://localhost:3000](http://localhost:3000))
* Manage API Docs ([http://localhost:3002/docs](http://localhost:3002/docs))
* Run API Docs ([http://localhost:3003/docs](http://localhost:3003/docs))
* Nango Dashboard ([http://localhost:3050](http://localhost:3050))
* SigNoz Dashboard ([http://localhost:3080](http://localhost:3080))
# Deploy to GCP Cloud Run
URL: /self-hosting/gcp-cloud-run
Deploy to GCP Cloud Run with Docker Containers
***
title: Deploy to GCP Cloud Run
sidebarTitle: GCP Cloud Run
description: Deploy to GCP Cloud Run with Docker Containers
icon: "LuCloudLightning"
------------------------
## Coming soon
# Deploy to GCP Compute Engine
URL: /self-hosting/gcp-compute-engine
Deploy to GCP Compute Engine with Docker Compose
***
title: Deploy to GCP Compute Engine
sidebarTitle: GCP Compute Engine
description: Deploy to GCP Compute Engine with Docker Compose
icon: "LuCloudSun"
------------------
## Create a VM Instance
* Go to [Compute Engine](https://console.cloud.google.com/compute/instances) in your GCP project.
* Create an instance; a recommended size is at least `e2-standard-2` (2 vCPU, 1 core, 8 GB memory).
* Use Debian GNU/Linux 12 (bookworm)
* Increase the size of the boot disk to 30 GB.
* Allow HTTP traffic.
* Allow ingress traffic from source IPv4 ranges `0.0.0.0/0` to TCP ports: `3000, 3002, 3003, 3050, 3051, 3080`. These are the ports exposed by the Inkeep services.
* Retrieve an external IP address (if applicable, set up a static IP or set up a load balancer).
## Install Docker Compose
1. [SSH into the VM](https://cloud.google.com/compute/docs/connect/standard-ssh)
2. [Set up Docker's apt repository](https://docs.docker.com/engine/install/debian/#install-using-the-repository)
```bash
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
```
3. Install the Docker packages
```bash
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
```
4. Grant permissions
```
sudo usermod -aG docker $USER
newgrp docker
```
## Deploy SigNoz and Nango
Clone this repo, which includes Docker files with SigNoz and Nango:
```bash
git clone https://github.com/inkeep/agents-optional-local-dev inkeep-external-services
cd inkeep-external-services
```
Run this command to autogenerate a `.env` file:
```bash
cp .env.example .env && \
encryption_key=$(openssl rand -base64 32) && \
tmp_file=$(mktemp) && \
sed "s||$encryption_key|" .env > "$tmp_file" && \
mv "$tmp_file" .env && \
echo "Docker environment file created with auto-generated encryption key"
```
Nango requires a `NANGO_ENCRYPTION_KEY`. Once you create this, it cannot be edited.
Here's an overview of the important environment variables when deploying to production. Make sure to replace all of these in the `.env` file.
```bash
NANGO_ENCRYPTION_KEY=
# Replace these with your in production!
NANGO_SERVER_URL=http://:3050
NANGO_PUBLIC_CONNECT_URL=http://:3051
# Modify these in production environments!
NANGO_DASHBOARD_USERNAME=admin@example.com
NANGO_DASHBOARD_PASSWORD=adminADMIN!@12
```
Build and deploy SigNoz, Nango, OTEL Collector, and Jaeger:
```bash
docker compose up -d
```
This may take up to 5 minutes to start.
### Retrieve your SigNoz and Nango API Keys
To get your SigNoz API key `SIGNOZ_API_KEY`:
* Open SigNoz in a browser at `http://:3080`
* Navigate to Settings → Account Settings → API Keys → New Key
* Choose a role, Viewer is sufficient for observability
* Set the expiration field to "No Expiry" to prevent the key from expiring
To get your Nango secret key `NANGO_SECRET_KEY`:
* Open Nango in a browser at `http://:3050`
* Nango auto-creates two environments, Prod and Dev. Select the one you will use.
* Navigate to Environment Settings to find the secret key
## Deploy the Inkeep Agent Framework
From the root directory, create a new project directory for the Docker Compose setup for the Inkeep Agent Framework
```bash
mkdir inkeep && cd inkeep
wget https://raw.githubusercontent.com/inkeep/agents/refs/heads/main/docker-compose.yml
wget https://raw.githubusercontent.com/inkeep/agents/refs/heads/main/.env.docker.example
```
Generate a `.env` file from the example:
```bash
cp .env.docker.example .env
```
Here's an overview of the important environment variables when deploying to production. Make sure to replace all of these in the `.env` file.
```bash
# Change to "production" if deploying to production
ENVIRONMENT=production
# AI Provider Keys (you need at least one)
ANTHROPIC_API_KEY=
OPENAI_API_KEY=
GOOGLE_GENERATIVE_AI_API_KEY=
# Nango
NANGO_SECRET_KEY=
# SigNoz
SIGNOZ_API_KEY=
# Uncomment and set each of these with (openssl rand -hex 32)
INKEEP_AGENTS_MANAGE_API_BYPASS_SECRET=
INKEEP_AGENTS_RUN_API_BYPASS_SECRET=
INKEEP_AGENTS_JWT_SIGNING_SECRET=
# Uncomment and set these for the Manage UI at http://:3000
PUBLIC_INKEEP_AGENTS_MANAGE_API_URL=http://:3002
PUBLIC_INKEEP_AGENTS_RUN_API_URL=http://:3003
PUBLIC_INKEEP_AGENTS_RUN_API_BYPASS_SECRET=
PUBLIC_NANGO_SERVER_URL=http://:3050
PUBLIC_NANGO_CONNECT_BASE_URL=http://:3051
PUBLIC_SIGNOZ_URL=http://:3080
# Uncomment and set these to access Manage UI at http://:3000
INKEEP_AGENTS_MANAGE_UI_USERNAME=admin@example.com
INKEEP_AGENTS_MANAGE_UI_PASSWORD=adminADMIN!@12
```
<>
:::tip Advanced Configuration
For long-running agents or custom deployment requirements, you can override runtime limits like execution timeouts, maximum transfers, and generation steps. See [Configure Runtime Limits](/docs/self-hosting/configure-runtime-limits) for examples and the complete list of overridable settings.
:::
>
Run with Docker:
```bash
docker compose up -d
```
Then open `http://:3000` in a browser!
# Deploy to Hetzner
URL: /self-hosting/hetzner
Deploy to Hetzner with Docker Compose
***
title: Deploy to Hetzner
sidebarTitle: Hetzner
description: Deploy to Hetzner with Docker Compose
icon: "LuServerCog"
-------------------
## Create a server
* Create a server, recommended size is at least CPX32 (4 VCPUS, 8 GB RAM, >30 GB Storage)
* Select Ubuntu 24.04 Image
* Create an inbound firewall rule to allow TCP ports: 3000, 3002, 3003, 3050, 3051, and 3080. These are the ports exposed by the Inkeep services.
## Install Docker Compose
1. SSH into the server as root
2. [Set up Docker's apt repository](https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository)
```bash
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
```
3. Install the Docker packages
```bash
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
```
## Deploy SigNoz and Nango
Clone this repo, which includes Docker files with SigNoz and Nango:
```bash
git clone https://github.com/inkeep/agents-optional-local-dev inkeep-external-services
cd inkeep-external-services
```
Run this command to autogenerate a `.env` file:
```bash
cp .env.example .env && \
encryption_key=$(openssl rand -base64 32) && \
tmp_file=$(mktemp) && \
sed "s||$encryption_key|" .env > "$tmp_file" && \
mv "$tmp_file" .env && \
echo "Docker environment file created with auto-generated encryption key"
```
Nango requires a `NANGO_ENCRYPTION_KEY`. Once you create this, it cannot be edited.
Here's an overview of the important environment variables when deploying to production. Make sure to replace all of these in the `.env` file.
```bash
NANGO_ENCRYPTION_KEY=
# Replace these with your in production!
NANGO_SERVER_URL=http://:3050
NANGO_PUBLIC_CONNECT_URL=http://:3051
# Modify these in production environments!
NANGO_DASHBOARD_USERNAME=admin@example.com
NANGO_DASHBOARD_PASSWORD=adminADMIN!@12
```
Build and deploy SigNoz, Nango, OTEL Collector, and Jaeger:
```bash
docker compose up -d
```
This may take up to 5 minutes to start.
### Retrieve your SigNoz and Nango API Keys
To get your SigNoz API key `SIGNOZ_API_KEY`:
* Open SigNoz in a browser at `http://:3080`
* Navigate to Settings → Account Settings → API Keys → New Key
* Choose a role, Viewer is sufficient for observability
* Set the expiration field to "No Expiry" to prevent the key from expiring
To get your Nango secret key `NANGO_SECRET_KEY`:
* Open Nango in a browser at `http://:3050`
* Nango auto-creates two environments, Prod and Dev. Select the one you will use.
* Navigate to Environment Settings to find the secret key
## Deploy the Inkeep Agent Framework
From the root directory, create a new project directory for the Docker Compose setup for the Inkeep Agent Framework
```bash
mkdir inkeep && cd inkeep
wget https://raw.githubusercontent.com/inkeep/agents/refs/heads/main/docker-compose.yml
wget https://raw.githubusercontent.com/inkeep/agents/refs/heads/main/.env.docker.example
```
Generate a `.env` file from the example:
```bash
cp .env.docker.example .env
```
Here's an overview of the important environment variables when deploying to production. Make sure to replace all of these in the `.env` file.
```bash
# Change to "production" if deploying to production
ENVIRONMENT=production
# AI Provider Keys (you need at least one)
ANTHROPIC_API_KEY=
OPENAI_API_KEY=
GOOGLE_GENERATIVE_AI_API_KEY=
# Nango
NANGO_SECRET_KEY=
# SigNoz
SIGNOZ_API_KEY=
# Uncomment and set each of these with (openssl rand -hex 32)
INKEEP_AGENTS_MANAGE_API_BYPASS_SECRET=
INKEEP_AGENTS_RUN_API_BYPASS_SECRET=
INKEEP_AGENTS_JWT_SIGNING_SECRET=
# Uncomment and set these for the Manage UI at http://:3000
PUBLIC_INKEEP_AGENTS_MANAGE_API_URL=http://:3002
PUBLIC_INKEEP_AGENTS_RUN_API_URL=http://:3003
PUBLIC_INKEEP_AGENTS_RUN_API_BYPASS_SECRET=
PUBLIC_NANGO_SERVER_URL=http://:3050
PUBLIC_NANGO_CONNECT_BASE_URL=http://:3051
PUBLIC_SIGNOZ_URL=http://:3080
# Uncomment and set these to access Manage UI at http://:3000
INKEEP_AGENTS_MANAGE_UI_USERNAME=admin@example.com
INKEEP_AGENTS_MANAGE_UI_PASSWORD=adminADMIN!@12
```
<>
:::tip Advanced Configuration
For long-running agents or custom deployment requirements, you can override runtime limits like execution timeouts, maximum transfers, and generation steps. See [Configure Runtime Limits](/docs/self-hosting/configure-runtime-limits) for examples and the complete list of overridable settings.
:::
>
Run with Docker:
```bash
docker compose up -d
```
Then open `http://:3000` in a browser!
# Deploy to Vercel
URL: /self-hosting/vercel
Deploy the Inkeep Agent Framework to Vercel
***
title: Deploy to Vercel
description: Deploy the Inkeep Agent Framework to Vercel
icon: "brand/VercelIcon"
------------------------
## Deploy to Vercel
### Step 1: Create a GitHub repository for your project
If you do not have an Inkeep project already, [follow these steps](/get-started/quick-start) to create one. Then push your project to a repository on GitHub.
### Step 2: Create a Postgres Database
Create a Postgres database on the [**Vercel Marketplace**](https://vercel.com/marketplace/neon) or directly at [**Neon**](https://neon.tech/).
### Step 3: Configure Database Connection
Set your database connection string as an environment variable:
```
DATABASE_URL=
```
### Step 4: Create a Vercel account
Sign up for a Vercel account [here](https://vercel.com/signup).
### Step 5: Create a Vercel project for Manage API

The Framework Preset should be "Hono" and the Root Directory should be
`apps/manage-api`.
Required environment variables for Manage API:
```
ENVIRONMENT=production
INKEEP_AGENTS_MANAGE_API_BYPASS_SECRET=
DATABASE_URL=
NANGO_SECRET_KEY=
NANGO_SERVER_URL=https://api.nango.dev
```
| Environment Variable | Value |
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `ENVIRONMENT` | `production` |
| `INKEEP_AGENTS_MANAGE_API_BYPASS_SECRET` | Run `openssl rand -hex 32` in your terminal to generate this value. Save this value for `INKEEP_AGENTS_MANAGE_API_BYPASS_SECRET` in Step 7. |
| `DATABASE_URL` | Postgres connection string from Step 3 (e.g., `postgresql://user:password@host:5432/database`) |
| `NANGO_SECRET_KEY` | Nango secret key from your [Nango Cloud account](/get-started/credentials#option-1-nango-cloud-setup). Note: Local Nango setup won't work with Vercel deployments. |
| `NANGO_SERVER_URL` | `https://api.nango.dev` |
### Step 6: Create a Vercel project for Run API

The Framework Preset should be "Hono" and the Root Directory should be
`apps/run-api`.
Required environment variables for Run API:
```
ENVIRONMENT=production
ANTHROPIC_API_KEY=
OPENAI_API_KEY=
GOOGLE_GENERATIVE_AI_API_KEY=
INKEEP_AGENTS_RUN_API_BYPASS_SECRET=
DATABASE_URL=
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://ingest.us.signoz.cloud:443/v1/traces
OTEL_EXPORTER_OTLP_TRACES_HEADERS=signoz-ingestion-key=
NANGO_SECRET_KEY=
NANGO_SERVER_URL=https://api.nango.dev
INKEEP_AGENTS_JWT_SIGNING_SECRET=
```
| Environment Variable | Value |
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `ENVIRONMENT` | `production` |
| `ANTHROPIC_API_KEY` | Your Anthropic API key |
| `OPENAI_API_KEY` | Your OpenAI API key |
| `GOOGLE_GENERATIVE_AI_API_KEY` | Your Google Gemini API key |
| `INKEEP_AGENTS_RUN_API_BYPASS_SECRET` | Run `openssl rand -hex 32` in your terminal to generate this value. Save this value for `INKEEP_AGENTS_RUN_API_BYPASS_SECRET` in Step 7. |
| `DATABASE_URL` | Postgres connection string from Step 3 (e.g., `postgresql://user:password@host:5432/database`) |
| `NANGO_SECRET_KEY` | Nango secret key from your [Nango Cloud account](/get-started/credentials#option-1-nango-cloud-setup). Note: Local Nango setup won't work with Vercel deployments. |
| `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` | `https://ingest.us.signoz.cloud:443/v1/traces` |
| `OTEL_EXPORTER_OTLP_TRACES_HEADERS` | `signoz-ingestion-key=`. Use the instructions from [SigNoz Cloud Setup](/get-started/traces#option-1-signoz-cloud-setup) to configure your ingestion key. Note: Local SigNoz setup won't work with Vercel deployments. |
| `NANGO_SERVER_URL` | `https://api.nango.dev` |
| `INKEEP_AGENTS_JWT_SIGNING_SECRET` | Run `openssl rand -hex 32` in your terminal to generate this value. Save this value for `INKEEP_AGENTS_JWT_SIGNING_SECRET` in Step 7. |
### Step 7: Create a Vercel project for Manage UI

The Framework Preset should be "Next.js" and the Root Directory should be
`apps/manage-ui`.
Required environment variables for Manage UI:
```
ENVIRONMENT=production
PUBLIC_INKEEP_AGENTS_RUN_API_URL=
PUBLIC_INKEEP_AGENTS_RUN_API_BYPASS_SECRET=
PUBLIC_INKEEP_AGENTS_MANAGE_API_URL=
INKEEP_AGENTS_MANAGE_API_URL=
INKEEP_AGENTS_MANAGE_API_BYPASS_SECRET=
PUBLIC_SIGNOZ_URL=https://.signoz.cloud
SIGNOZ_API_KEY=
PUBLIC_NANGO_SERVER_URL=https://api.nango.dev
PUBLIC_NANGO_CONNECT_BASE_URL=https://connect.nango.dev
NANGO_SECRET_KEY=
```
| Environment Variable | Value |
| -------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ENVIRONMENT` | `production` |
| `PUBLIC_INKEEP_AGENTS_RUN_API_URL` | Your Vercel deployment URL for Run API |
| `PUBLIC_INKEEP_AGENTS_RUN_API_BYPASS_SECRET` | Your generated Run API bypass secret from Step 6 |
| `PUBLIC_INKEEP_AGENTS_MANAGE_API_URL` | Your Vercel deployment URL for Manage API (skip if same as `INKEEP_AGENTS_MANAGE_API_URL`) |
| `INKEEP_AGENTS_MANAGE_API_URL` | Your Vercel deployment URL for Manage API |
| `INKEEP_AGENTS_MANAGE_API_BYPASS_SECRET` | Your generated Manage API bypass secret from Step 5 |
| `PUBLIC_SIGNOZ_URL` | Use the instructions from [SigNoz Cloud Setup](/get-started/traces#option-1-signoz-cloud-setup) to configure your SigNoz URL. Note: Local SigNoz setup won't work with Vercel deployments. |
| `SIGNOZ_API_KEY` | Use the instructions from [SigNoz Cloud Setup](/get-started/traces#option-1-signoz-cloud-setup) to configure your SigNoz API key. Note: Local SigNoz setup won't work with Vercel deployments. |
| `NANGO_SECRET_KEY` | Nango secret key from your [Nango Cloud account](/get-started/credentials#option-1-nango-cloud-setup). Note: Local Nango setup won't work with Vercel deployments. |
| `PUBLIC_NANGO_SERVER_URL` | `https://api.nango.dev` |
| `PUBLIC_NANGO_CONNECT_BASE_URL` | `https://connect.nango.dev` |
### Step 8: Enable Vercel Authentication
To prevent anyone from being able to access the UI, we recommend enabling Vercel authentication for all deployments: **Settings > Deployment Protection > Vercel Authentication > All Deployments**.
### Step 9: Create a Vercel project for your MCP server (optional)

The Framework Preset should be "Next.js" and the Root Directory should be
`apps/mcp`.
For more information on how to add MCP servers to your project, see [Create MCP Servers](/typescript-sdk/cli-reference#inkeep-add).
## Push your Agent
### Step 1: Configure your root .env file
```
INKEEP_AGENTS_MANAGE_API_BYPASS_SECRET=
INKEEP_AGENTS_RUN_API_BYPASS_SECRET=
```
### Step 2: Create a cloud configuration file
Create a new configuration file named `inkeep-cloud.config.ts` in your project's `src` directory, alongside your existing configuration file.
```typescript
import { defineConfig } from "@inkeep/agents-cli/config";
const config = defineConfig({
tenantId: "default",
agentsManageApi: {
url: "https://",
apiKey: process.env.INKEEP_AGENTS_MANAGE_API_BYPASS_SECRET,
},
agentsRunApi: {
url: "https://",
apiKey: process.env.INKEEP_AGENTS_RUN_API_BYPASS_SECRET,
},
});
export default config;
```
### Step 3: Push your Agent
```bash
cd /src/
inkeep push --config ../inkeep-cloud.config.ts
```
## Pull your Agent
```bash
cd /src
inkeep pull --config inkeep-cloud.config.ts
```
## Function Tools with Vercel Sandbox
When deploying to serverless environments like Vercel, you can configure [function tools](/typescript-sdk/tools/function-tools) to execute in [Vercel Sandbox](https://vercel.com/docs/vercel-sandbox) MicroVMs instead of your Agent's runtime service. This is **required** for serverless platforms since child process spawning is restricted.
### Why Use Vercel Sandbox?
**When to use each provider:**
* **Native** - Use for traditional cloud deployments (VMs, Docker, Kubernetes), self-hosted servers, or local development
* **Vercel Sandbox** - Required for serverless platforms (Vercel, AWS Lambda, etc.) or if you'd like to isolate tool executions
### Setting Up Vercel Sandbox
#### Step 1: Get Vercel Credentials
You'll need three credentials from your Vercel account:
1. **Vercel Token** - Create an access token at [vercel.com/account/tokens](https://vercel.com/account/tokens)
2. **Team ID** - Find in your team settings at [vercel.com/teams](https://vercel.com/teams)
3. **Project ID** - Find in your Vercel project settings
#### Step 2: Configure Sandbox in Your Application
Update your Run API to use Vercel Sandbox.
In the `apps/run-api/src` folder, create a `sandbox.ts` file:
```typescript sandbox.ts
const isProduction = process.env.ENVIRONMENT === "production";
export const sandboxConfig = isProduction
? {
provider: "vercel",
runtime: "node22", // or 'typescript'
timeout: 60000, // 60 second timeout
vcpus: 4, // Allocate 4 vCPUs
teamId: process.env.SANDBOX_VERCEL_TEAM_ID!,
projectId: process.env.SANDBOX_VERCEL_PROJECT_ID!,
token: process.env.SANDBOX_VERCEL_TOKEN!,
}
: {
provider: "native",
runtime: "node22",
timeout: 30000,
vcpus: 2,
};
```
Import it into your `index.ts` file:
```typescript index.ts
import { sandboxConfig } from "./sandbox.ts";
// ...
const app: Hono = createExecutionApp({
// ...
sandboxConfig, // NEW
});
```
#### Step 3: Add Environment Variables to Run API
Add these [environment variables in your Vercel project](https://vercel.com/docs/environment-variables/managing-environment-variables#declare-an-environment-variable) to your **Run API** app:
```bash
SANDBOX_VERCEL_TOKEN=your_vercel_access_token
SANDBOX_VERCEL_TEAM_ID=team_xxxxxxxxxx
SANDBOX_VERCEL_PROJECT_ID=prj_xxxxxxxxxx
```
"Failed to refresh OIDC token" error:
This occurs when you're not in a Vercel environment or you don't provide a Vercel access token
# Talk to your agent via A2A (JSON-RPC)
URL: /talk-to-your-agents/a2a
Use the Agent2Agent JSON-RPC protocol to send messages to your agent and receive results, with optional streaming.
***
title: Talk to your agent via A2A (JSON-RPC)
sidebarTitle: Agent2Agent API
description: Use the Agent2Agent JSON-RPC protocol to send messages to your agent and receive results, with optional streaming.
icon: "LuNetwork"
-----------------
The A2A (Agent-to-Agent) endpoint lets third-party agents, agent platforms, or agent workspaces interact with your Inkeep Agent using a standard agent protocol.
Here are some example platforms that you can add Inkeep Agents to:
| Platform | Description |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| **[Google Gemini Enterprise](https://cloud.google.com/gemini-enterprise/faq)** | Bring‑your‑own A2A agents into an enterprise agentspace and orchestrate alongside Google/vendor agents. |
| **[Microsoft Copilot Studio / Azure AI Foundry](https://microsoftlearning.github.io/mslearn-ai-agents/Instructions/06-multi-remote-agents-with-a2a.html)** | Copilots can invoke external A2A agents as peer services in multi‑agent flows. |
| **[Salesforce Agentforce](https://architect.salesforce.com/fundamentals/agentic-patterns)** | Add third‑party A2A agents (e.g., via AgentExchange) and compose them in CRM workflows. |
| **[SAP Joule](https://learning.sap.com/courses/boosting-ai-driven-business-transformation-with-joule-agents/enabling-interoperability-for-ai-agents)** | Federate non‑SAP A2A agents into SAP’s business agent fabric. |
| **[ServiceNow AI Agent Fabric](https://www.servicenow.com/community/now-assist-articles/introducing-ai-agent-fabric-enable-mcp-and-a2a-for-your-agentic/ta-p/3373907)** | Discover and call external A2A agents within IT/business automations. |
| **[Atlassian Rovo](https://support.atlassian.com/atlassian-rovo-mcp-server/docs/getting-started-with-the-atlassian-remote-mcp-server/)** | Configure Rovo to call external A2A agents for cross‑tool tasks. |
| **[Workday AI (Agent Gateway / ASOR)](https://investor.workday.com/2025-06-03-Workday-Announces-New-AI-Agent-Partner-Network-and-Agent-Gateway-to-Power-the-Next-Generation-of-Human-and-Digital-Workforces)** | Register external customer/partner A2A agents alongside Workday agents. |
<>
## Authentication
Choose the authentication method:
**Create an API Key:**
1. Open the Visual Builder Dashboard
2. Go to your Project → **API Keys**
3. Click **Create**, select the target agent
4. Copy the API key (it will be shown once) and store it securely
**Request Header:**
```http
Authorization: Bearer
```
When running the API server locally with `pnpm dev`, authentication is automatically bypassed. You can use headers in the request instead:
**Request Headers:**
```http
x-inkeep-tenant-id:
x-inkeep-project-id:
x-inkeep-agent-id:
```
This mode is for development only. Never use in production as it bypasses all security checks.
See [Authentication → Run API](/api-reference/authentication/run-api) for more details.
>
## Endpoints
* **Agent card discovery (agent or sub-agent-level):** `GET /agents/.well-known/agent.json`
* **A2A protocol (agent or sub-agent-level):** `POST /agents/.well-known/agent.json`
Notes:
* If you supply `x-inkeep-sub-agent-id` in headers, requests target that specific Sub Agent. This is supported in development (or when using the bypass secret). With production API keys, requests always use the Agent's default Sub Agent.
## Message Send (Blocking)
* **Path:** `POST /agents/a2a`
* **Headers:** Per Authentication section (Standard API Key recommended)
* **Body (JSON-RPC 2.0):**
```json
{
"jsonrpc": "2.0",
"method": "message/send",
"id": 1,
"params": {
"message": {
"messageId": "msg-123",
"role": "user",
"parts": [
{ "kind": "text", "text": "Hello!" }
],
"contextId": "conv-123",
"kind": "message"
},
"configuration": {
"acceptedOutputModes": ["text", "text/plain"],
"blocking": true
}
}
}
```
* **Success Response (Message):**
```json
{
"jsonrpc": "2.0",
"result": {
"kind": "message",
"messageId": "auto-generated",
"role": "agent",
"parts": [ { "kind": "text", "text": "..." } ],
"taskId": "task-...",
"contextId": "conv-123"
},
"id": 1
}
```
* **Transfer Case:** if the agent decides to transfer, the response contains a `task` with a transfer artifact:
```json
{
"jsonrpc": "2.0",
"result": {
"kind": "task",
"id": "task-...",
"contextId": "conv-123",
"status": { "state": "completed", "timestamp": "..." },
"artifacts": [
{
"artifactId": "...",
"parts": [
{ "kind": "data", "data": { "type": "transfer", "targetSubAgentId": "other-agent-id" } },
{ "kind": "text", "text": "Transfer reason text" }
]
}
]
},
"id": 1
}
```
## Message Send (Non-blocking)
Set `configuration.blocking` to `false`. The server immediately returns a `task`, and you can poll or stream updates.
* **Request:** same as above, with `"blocking": false`
* **Response (Task):**
```json
{
"jsonrpc": "2.0",
"result": {
"kind": "task",
"id": "task-...",
"contextId": "conv-123",
"status": { "state": "completed", "timestamp": "..." },
"artifacts": [ { "artifactId": "...", "parts": [ { "kind": "text", "text": "..." } ] } ]
},
"id": 1
}
```
## Streaming Messages (SSE)
* **Path:** `POST /agents/a2a`
* **Headers:** include `Accept: text/event-stream` plus Authentication headers
* **Body (JSON-RPC 2.0):** same as blocking, but method `"message/stream"`
```json
{
"jsonrpc": "2.0",
"method": "message/stream",
"id": 2,
"params": {
"message": {
"messageId": "msg-456",
"role": "user",
"parts": [ { "kind": "text", "text": "Stream please" } ],
"contextId": "conv-123",
"kind": "message"
},
"configuration": {
"acceptedOutputModes": ["text", "text/plain"],
"blocking": false
}
}
}
```
* **SSE Events (each line is an SSE `data:` payload containing JSON-RPC):**
```text
: keep-alive
data: {"jsonrpc":"2.0","result":{"kind":"task","id":"task-...","contextId":"conv-123","status":{"state":"working","timestamp":"..."},"artifacts":[]},"id":2}
data: {"jsonrpc":"2.0","result":{"kind":"message","messageId":"...","role":"agent","parts":[{"kind":"text","text":"..."}],"taskId":"task-...","contextId":"conv-123"},"id":2}
data: {"jsonrpc":"2.0","result":{"kind":"task","id":"task-...","contextId":"conv-123","status":{"state":"completed","timestamp":"..."},"artifacts":[{"artifactId":"...","parts":[{"kind":"text","text":"..."}]}]},"id":2}
```
* **Transfer (streaming):** if a transfer is triggered, an SSE event with a JSON-RPC `result` of transfer details is sent, then the stream ends.
## Task APIs
* **Get task:** `POST /agents/a2a` with method `"tasks/get"` and params `{ "id": "task-..." }` → returns the `task`
* **Cancel task:** `POST /agents/a2a` with method `"tasks/cancel"` and params `{ "id": "task-..." }` → returns `{ "success": true }`
* **Resubscribe (SSE, mock):** `POST /agents/a2a` with method `"tasks/resubscribe"` and params `{ "taskId": "task-..." }` → SSE with a task event
Currently, `tasks/get` and `tasks/cancel` return stubbed responses, and `tasks/resubscribe` returns a mock SSE event. For live progress updates, use `message/stream`.
## Agent Card Discovery
* **Agent-level:** `GET /agents/.well-known/agent.json` (uses Agent's default Sub Agent)
* **Agent-level (dev/bypass only):** Provide `x-inkeep-sub-agent-id` in headers to target a specific agent for discovery
## Notes & Behavior
* **contextId resolution:** The server first tries `task.context.conversationId` (derived from the request), then `params.message.metadata.conversationId`. Final fallback is `'default'`.
* **Artifacts in responses:** Message/Task responses may include `artifacts[0].parts` as the agent's output parts.
* **Errors (JSON-RPC):** Standard JSON-RPC error codes: `-32600`, `-32601`, `-32602`, `-32603`, `-32700`, plus A2A-specific `-3200x` codes.
## Development Notes
* **Base URL (local):** `http://localhost:3003`
* **Route Mounting:** A2A routes are mounted under `/agents`; use `/agents/a2a` for RPC and `/agents/.well-known/agent.json` for discovery
* **Streaming support:** Requires agent capabilities `streaming: true` in the agent card
# How to call your AI Agent using the Chat API
URL: /talk-to-your-agents/chat-api
Learn about details of the Vercel AI SDK data stream protocol that powers the `/chat` API endpoint.
***
title: How to call your AI Agent using the Chat API
sidebarTitle: Chat API
description: Learn about details of the Vercel AI SDK data stream protocol that powers the `/chat` API endpoint.
icon: LuMessagesSquare
keywords: API, Vercel AI SDK, streaming, SSE, data stream, agents, chat
-----------------------------------------------------------------------
## Overview
This guide shows how to call your agent directly over HTTP and stream responses using the Vercel AI SDK data stream format. It covers the exact endpoint, headers, request body, and the event stream response you should expect.
If you are building a React UI, consider our prebuilt components under [React UI Components](/talk-to-your-agents/react/chat-button) or [Vercel AI Elements](/talk-to-your-agents/vercel-ai-sdk/ai-elements) headless primatives. This page is for the low-level streaming API.
## Endpoint
* **Path (mounted by the Run API):** `/api/chat`
* **Method:** `POST`
* **Protocol:** Server-Sent Events (SSE) encoded JSON, using Vercel AI SDK data-stream v2
* **Content-Type (response):** `text/event-stream`
* **Response Header:** `x-vercel-ai-data-stream: v2`
<>
## Authentication
Choose the authentication method:
**Create an API Key:**
1. Open the Visual Builder Dashboard
2. Go to your Project → **API Keys**
3. Click **Create**, select the target agent
4. Copy the API key (it will be shown once) and store it securely
**Request Header:**
```http
Authorization: Bearer
```
When running the API server locally with `pnpm dev`, authentication is automatically bypassed. You can use headers in the request instead:
**Request Headers:**
```http
x-inkeep-tenant-id:
x-inkeep-project-id:
x-inkeep-agent-id:
```
This mode is for development only. Never use in production as it bypasses all security checks.
See [Authentication → Run API](/api-reference/authentication/run-api) for more details.
>
## Request Body Schema
```json
{
"messages": [
{
"role": "user",
"content": "Hello!"
}
],
"conversationId": "optional-conversation-id"
}
```
**Field Notes:**
* **`messages`** — Must include at least one `user` message
* **`content`** — Can be a string or an object with `parts` for multi-part content
* **`conversationId`** — Optional; server generates one if omitted
### Optional Headers
* **`x-emit-operations`** — Set to `true` to include detailed data operations in the response stream. Useful for debugging and monitoring agent behavior. See [Data Operations](/typescript-sdk/data-operations) for details.
### Example cURL
When using an API key for auth:
```bash
curl -N \
-X POST "http://localhost:3003/api/chat" \
-H "Authorization: Bearer $INKEEP_API_KEY" \
-H "Content-Type: application/json" \
-H "x-emit-operations: true" \
-d '{
"messages": [
{ "role": "user", "content": "What can you do?" }
],
"conversationId": "chat-1234"
}'
```
## Response: Vercel AI SDK Data Stream (v2)
The response is an SSE stream of JSON events compatible with the Vercel AI SDK UI message stream. The server sets `x-vercel-ai-data-stream: v2`.
### Event Types
#### Text Streaming Events
* **`text-start`** — Indicates a new text segment is starting
* **`text-delta`** — Carries the text content delta for the current segment
* **`text-end`** — Marks the end of the current text segment
#### Data Events
* **`data-component`** — Structured UI data emitted by the agent (for rich UIs)
* **`data-artifact`** — Artifact data emitted by tools/agents (documents, files, saved results)
* **`data-operation`** — Low-level operational events (agent lifecycle, completion, errors)
* **`data-summary`** — AI-generated status updates with user-friendly labels and contextual details
### Example Stream (abbreviated)
```text
: keep-alive
data: {"type":"text-start","id":"1726247200-abc123"}
data: {"type":"text-delta","id":"1726247200-abc123","delta":"Hello! I can help with..."}
data: {"type":"data-summary","data":{"label":"Searching documentation","details":{"summary":"Looking for relevant information","progress":"25%"}}}
data: {"type":"text-delta","id":"1726247200-abc123","delta":" analyzing your query..."}
data: {"type":"text-end","id":"1726247200-abc123"}
data: {"type":"data-operation","data":{"type":"completion","ctx":{"agent":"search-agent","iteration":1}}}
data: {"type":"data-component","id":"1726247200-abc123-0","data":{"type":"customer-info","name":"Ada","email":"ada@example.com"}}
data: {"type":"data-artifact","data":{"artifact_id":"art_abc","task_id":"task_xyz","summary":{"title":"Search Results"}}}
```
### Data Event Details
#### `data-operation` Events
Low-level operational events with technical context. Common types include:
* **`agent_initializing`** — The agent runtime is starting
* **`agent_ready`** — Agent is ready and processing
* **`completion`** — The agent completed the task (includes agent ID and iteration count)
* **`error`** — Error information (also emitted as a top-level `error` event)
```json
{"type":"data-operation","data":{"type":"completion","ctx":{"agent":"search-agent","iteration":1}}}
```
#### `data-summary` Events
AI-generated status updates designed for end-user consumption. Structure:
* **`label`** — User-friendly description (required)
* **`details`** — Optional structured/unstructured context data
```json
{"type":"data-summary","data":{"label":"Processing search results","details":{"summary":"Found 12 relevant documents","itemsProcessed":12,"status":"analyzing"}}}
```
#### `data-artifact` Events
Saved documents, files, or structured results from tool executions:
```json
{"type":"data-artifact","data":{"artifact_id":"art_123","task_id":"task_456","summary":{"title":"Weather Report","type":"document"}}}
```
#### `data-component` Events
Structured UI data for rich interface components:
```json
{"type":"data-component","id":"comp_123","data":{"type":"chart","title":"Sales Data","chartData":[1,2,3]}}
```
### Text Streaming Behavior
* For each text segment, the server emits `text-start` → `text-delta` → `text-end`
* The server avoids splitting content word-by-word; a segment is usually a coherent chunk
* Operational events are queued during active text emission and flushed shortly after to preserve ordering and readability
## Error Responses
### Streamed Errors
Errors are now delivered as `data-operation` events with unified structure:
```json
{
"type": "data-operation",
"data": {
"type": "error",
"message": "Error description",
"agent": "agent-id",
"severity": "error",
"code": "optional-error-code",
"timestamp": 1640995200000
}
}
```
### Non-Streaming Errors
Validation failures and other errors return JSON with an appropriate HTTP status code.
## HTTP Status Codes
* **`200`** — Stream opened successfully
* **`401`** — Missing/invalid authentication
* **`404`** — Agent not found
* **`400`** — Invalid request body/context
* **`500`** — Internal server error
## Development Notes
* **Default local base URL:** `http://localhost:3003`
* **Endpoint mounting in the server:**
* `/api/chat` → Vercel data stream (this page)
* `/v1/mcp` → MCP JSON-RPC endpoint
To test quickly without a UI, use `curl -N` or a tool that supports Server-Sent Events.
# MCP Server
URL: /talk-to-your-agents/mcp-server
Learn how to use the MCP server to talk to your agents
***
title: MCP Server
description: Learn how to use the MCP server to talk to your agents
icon: "LuServer"
----------------
The MCP server allows you to talk to your agents through the Model Context Protocol.
<>
## Authentication
Choose the authentication method:
**Create an API Key:**
1. Open the Visual Builder Dashboard
2. Go to your Project → **API Keys**
3. Click **Create**, select the target agent
4. Copy the API key (it will be shown once) and store it securely
**Request Header:**
```http
Authorization: Bearer
```
When running the API server locally with `pnpm dev`, authentication is automatically bypassed. You can use headers in the request instead:
**Request Headers:**
```http
x-inkeep-tenant-id:
x-inkeep-project-id:
x-inkeep-agent-id:
```
This mode is for development only. Never use in production as it bypasses all security checks.
See [Authentication → Run API](/api-reference/authentication/run-api) for more details.
>
## MCP Server Implementation
The MCP server is implemented in the `@inkeep/agents-run-api` library and provides a standard interface for agent communication.
## Available Tools
The MCP server exposes one core tool:
### send-query-to-agent
Sends a query to your agent's default sub-agent. This tool:
* **Name**: `send-query-to-agent`
* **Description**: Dynamically generated based on your agent's name and description
* **Parameters**:
* `query` (string): The query to send to the agent
* **Returns**: The agent's response as text content
**Example usage in Cursor:**
When the MCP server is configured, Cursor will automatically discover this tool and you can use it by asking questions. The tool will route your query to the appropriate sub-agent in your agent and return the response.
The tool handles:
* Message creation and conversation management
* Sub-agent execution with your configured tools and capabilities
* Context resolution if your agent has context configuration
* Error handling and response formatting
## Using with Cursor
### Quick Install (Inkeep Hosted Docs MCP)
Install the Inkeep Agents documentation MCP server with one click:
### Manual Configuration
Add the following configuration to your Cursor MCP settings.
#### Example
Example when using an API key for auth:
```json
{
"AgentName": {
"type": "mcp",
"url": "http:///v1/mcp",
"headers": {
"Authorization": "Bearer "
}
}
}
```
## Session Management (Required by MCP HTTP Transport)
* Initialize a session by sending an `initialize` JSON-RPC request to `/v1/mcp`.
* The server will respond and set `Mcp-Session-Id` in response headers.
* For all subsequent JSON-RPC requests in that session, include `Mcp-Session-Id` header with the value from initialization.
Session management is required by MCP’s HTTP transport. If `Mcp-Session-Id` is
missing or invalid on follow-up requests, the server will return a JSON-RPC
error (e.g., "Session not found").
## Configuration Notes
* **URL**: Point to your `agents-run-api` instance (default: `http://localhost:3003`)
* **Headers**: Use the appropriate authentication mode per the section above
* **Authorization**: Only required outside development mode
# Overview
URL: /talk-to-your-agents/overview
Learn how to talk to your agents
***
title: Overview
description: Learn how to talk to your agents
icon: "LuMessageSquare"
-----------------------
<>
You can talk to an Inkeep Agent in a few ways, including:
* **UI Chat Components**: Drop-in React components for chat UIs with built-in streaming and rich UI customization. See [`agents-ui`](/talk-to-your-agents/react/chat-button).
* **As an MCP server**: Use your Inkeep Agent as if was an MCP Server. Allows you to connect it to any MCP client, like Claude, ChatGPT, Claude and other Agents. See [MCP server](/talk-to-your-agents/mcp-server).
* **Via API (Vercel format)**: An API that streams responses over server-side events (SSE). Use from any language/runtime, including the Vercel's `useChat` and AI Element primitives for custom UIs. See [API (Vercel format)](/talk-to-your-agents/api).
* **Via API (A2A format)**: An API that follows the Agent-to-Agent ('A2A') JSON-RPC protocol. Great for when combining Inkeep with different Agent frameworks that support the A2A format. See [A2A protocol](/talk-to-your-agents/a2a).
Drop-in chat components for React apps with streaming and rich UI.
POST /api/chat, SSE (text/event-stream), x-vercel-ai-data-stream: v2.
JSON-RPC messages at /agents/a2a with blocking and streaming modes.
HTTP JSON-RPC endpoint at /v1/mcp with session header management.
>
# Upgrading your Inkeep version
URL: /tutorials/upgrading
Upgrade the packages that make up the Inkeep Agent Framework
***
title: Upgrading your Inkeep version
sidebarTitle: Upgrading
description: Upgrade the packages that make up the Inkeep Agent Framework
icon: "LuPackage"
-----------------
## Overview
The Inkeep Agent Framework is composed of several npm packages:
* [`@inkeep/agents-manage-api`](https://www.npmjs.com/package/@inkeep/agents-manage-api): The API for managing projects and agent configurations.
* [`@inkeep/agents-run-api`](https://www.npmjs.com/package/@inkeep/agents-run-api): The API for executing conversations with your agents.
* [`@inkeep/agents-manage-ui`](https://www.npmjs.com/package/@inkeep/agents-manage-ui): The UI for the visual builder and dashboard.
* [`@inkeep/agents-core`](https://www.npmjs.com/package/@inkeep/agents-core): The core shared functionality of the agent framework.
* [`@inkeep/agents-sdk`](https://www.npmjs.com/package/@inkeep/agents-sdk): The TypeScript SDK for building multi-agent systems.
* [`@inkeep/agents-cli`](https://www.npmjs.com/package/@inkeep/agents-cli): The CLI for managing and interacting with the agent framework.
* [`@inkeep/agents-ui`](https://www.npmjs.com/package/@inkeep/agents-ui): The UI library containing chat widget components.
## Upgrading the quickstart template
If you used the `npx @inkeep/create-agents` CLI command to create your workspace, run the following command from the workspace root:
```bash
pnpm upgrade-agents
```
This will update all the packages to the latest version and migrate your database schema to the latest version.
## Upgrading the Agent CLI
If you installed the `@inkeep/agents-cli` package globally, you can upgrade it to the latest version by running the following command:
```bash
inkeep update
```
# Sub Agent Relationships
URL: /typescript-sdk/agent-relationships
Learn how to add Sub Agent relationships to your agent
***
title: Sub Agent Relationships
description: Learn how to add Sub Agent relationships to your agent
icon: "LuUsers"
---------------
Sub Agent relationships are used to coordinate specialized Sub Agents for complex workflows. This framework implements Sub Agent relationships through using `canDelegateTo()` and `canTransferTo()`, allowing a parent Sub Agent to automatically coordinate specialized Sub Agents for complex workflows.
## Understanding Sub Agent Relationships
The framework supports two types of Sub Agent relationships:
### Transfer Relationships
Transfer relationships **completely relinquish control** from one Sub Agent to another. When a Sub Agent hands off to another:
* The source Sub Agent stops processing
* The target Sub Agent takes full control of the conversation
* Control is permanently transferred until the target Sub Agent hands back
```typescript
import { subAgent, agent } from "agent-sdk";
// Create specialized Sub Agents first
const qaSubAgent = subAgent({
id: "qa-agent",
name: "QA Sub Agent",
description: "Answers product and service questions",
prompt: "Provide accurate information using available tools. Hand back to router if unable to help.",
canUse: () => [knowledgeBaseTool],
canTransferTo: () => [routerSubAgent],
});
const orderSubAgent = subAgent({
id: "order-agent",
name: "Order Sub Agent",
description: "Handles order-related inquiries and actions",
prompt: "Assist with order tracking, modifications, and management.",
canUse: () => [orderSystemTool],
canTransferTo: () => [routerSubAgent],
});
// Create router Sub Agent that coordinates other Sub Agents
const routerSubAgent = subAgent({
id: "router-agent",
name: "Router Sub Agent",
description: "Routes customer inquiries to specialized Sub Agents",
prompt: `Analyze customer inquiries and route them appropriately:
- Product questions → Hand off to QA Sub Agent
- Order issues → Hand off to Order Sub Agent
- Complex issues → Handle directly or escalate`,
canTransferTo: () => [qaSubAgent, orderSubAgent],
});
// Create the agent with router as default entry point
const supportAgent = agent({
id: "customer-support-agent",
defaultSubAgent: routerSubAgent,
subAgents: () => [routerSubAgent, qaSubAgent, orderSubAgent],
models: {
base: {
model: "anthropic/claude-sonnet-4-5",
providerOptions: {
temperature: 0.5,
},
},
structuredOutput: {
model: "openai/gpt-4.1-mini",
},
},
});
```
### Delegation Relationships
Delegation relationships are used to **pass a task** from one Sub Agent to another while maintaining oversight:
* The source Sub Agent remains in control
* The target Sub Agent executes a specific task
* Results are returned to the source Sub Agent
* The source Sub Agent continues processing
```typescript
// Sub Agents for specific tasks
const numberProducerA = subAgent({
id: "number-producer-a",
name: "Number Producer A",
description: "Produces low-range numbers (0-50)",
prompt: "Generate numbers between 0 and 50. Respond with a single integer.",
});
const numberProducerB = subAgent({
id: "number-producer-b",
name: "Number Producer B",
description: "Produces high-range numbers (50-100)",
prompt: "Generate numbers between 50 and 100. Respond with a single integer.",
});
// Coordinating Sub Agent that delegates tasks
const mathSupervisor = subAgent({
id: "math-supervisor",
name: "Math Supervisor",
description: "Coordinates mathematical operations",
prompt: `When given a math task:
1. Delegate to Number Producer A for a low number
2. Delegate to Number Producer B for a high number
3. Add the results together and provide the final answer`,
canDelegateTo: () => [numberProducerA, numberProducerB],
});
const mathAgent = agent({
id: "math-delegation-agent",
defaultSubAgent: mathSupervisor,
subAgents: () => [mathSupervisor, numberProducerA, numberProducerB],
models: {
base: {
model: "anthropic/claude-haiku-4-5",
providerOptions: {
temperature: 0.1,
}
}
},
});
```
## When to Use Each Relationship
### Use Transfers for Complex Tasks
Use `canTransferTo` when the task is complex and the user will likely want to ask follow-up questions to the specialized Sub Agent:
* **Customer support conversations** - User may have multiple related questions
* **Technical troubleshooting** - Requires back-and-forth interaction
* **Order management** - User might want to modify, track, or ask about multiple aspects
* **Product consultations** - Users often have follow-up questions
### Use Delegation for Simple Tasks
Use `canDelegateTo` when the task is simple and self-contained:
* **Data retrieval** - Get a specific piece of information and return it
* **Calculations** - Perform a computation and return the result
* **Single API calls** - Make one external request and return the data
* **Simple transformations** - Convert data from one format to another
```typescript
// TRANSFER: User will likely have follow-up questions about their order
const routerSubAgent = subAgent({
id: "router",
prompt: "For order inquiries, transfer to order specialist",
canTransferTo: () => [orderSubAgent],
});
// DELEGATION: Just need a quick calculation, then continue
const mathSupervisor = subAgent({
id: "supervisor",
prompt: "Delegate to number producers, then add results together",
canDelegateTo: () => [numberProducerA, numberProducerB],
});
```
## Types of Delegation Relationships
### Sub Agent Delegation
Sub agent delegation is used to delegate a task to a sub agent as seen above.
### External Agent Delegation
External agent delegation is used to delegate a task to an [external agent](/typescript-sdk/external-agents).
```typescript
import { myExternalAgent } from "./external-agents/external-agent-example";
const mathSupervisor = subAgent({
id: "supervisor",
prompt: "Delegate to the external agent to calculate the answer to the question",
canDelegateTo: () => [myExternalAgent],
});
```
You can also specify headers to include with every request to the external agent.
```typescript
const mathSupervisor = subAgent({
id: "supervisor",
prompt: "Delegate to the external agent to calculate the answer to the question",
canDelegateTo: () => [myExternalAgent.with({ headers: { "authorization": "my-api-key" } })],
});
```
### Team Agent Delegation
Team agent delegation is used to delegate a task to another agent in the same project.
```typescript
import { myAgent } from "./agents/my-team-agent";
const mathSupervisor = subAgent({
id: "supervisor",
prompt: "Delegate to the team agent to calculate the answer to the question",
canDelegateTo: () => [myAgent],
});
```
You can also specify headers to include with every request to the team agent.
```typescript
const mathSupervisor = subAgent({
id: "supervisor",
prompt: "Delegate to the team agent to calculate the answer to the question",
canDelegateTo: () => [myAgent.with({ headers: { "authorization": "my-api-key" } })],
});
```
# Agents & Sub Agents
URL: /typescript-sdk/agent-settings
Learn how to customize your Agents.
***
title: Agents & Sub Agents
description: Learn how to customize your Agents.
icon: "LuUser"
--------------
Agents and Sub Agents are the core building blocks of the Inkeep Agent framework.
An Agent is made up of one or more Sub Agents that can delegate or transfer control with each other, share context, use tools to respond to a user or complete a task.
## Creating an Agent
An Agent is your top-level entity that you as a user interact with or can trigger programmatically.
An Agent is made up of sub-agents, like so:
```typescript
// Agent-level prompt that gets added to all Sub Agents
const customerSupportAgent = agent({
id: "support-agent",
prompt: `You work for Acme Corp. Always be professional and helpful.`,
subAgents: () => [supportAgent, escalationAgent],
});
```
**The `prompt` is automatically put into context and added into each Sub Agent's system prompt.** This provides consistent behavior and tone to all Sub Agents so they can act and respond as one cohesive unit to the end-user.
## Creating a Sub Agent
Like an Agent, a Sub Agent needs an id, name, and clear prompt that define its behavior:
```typescript
import { subAgent } from "@inkeep/agents-sdk";
const supportAgent = subAgent({
id: "customer-support",
name: "Customer Support Agent",
prompt: `You are a customer support specialist.`,
});
```
## Configuring Models
Configure AI models for your agents. See [Model Configuration](/typescript-sdk/models) for detailed information about supported providers, configuration options, and examples.
## Configuring StopWhen
Control stopping conditions to prevent infinite loops:
```typescript
// Agent level - limit transfers between Sub Agents
agent({
id: "support-agent",
stopWhen: {
transferCountIs: 5 // Max transfers in one conversation
},
});
// Sub Agent level - limit generation steps
subAgent({
id: "my-sub-agent",
stopWhen: {
stepCountIs: 20 // Max tool calls + LLM responses
},
});
```
**Configuration levels:**
* `transferCountIs`: Project or Agent level
* `stepCountIs`: Project or Sub Agent level
Settings inherit from Project → Agent → Sub Agent.
## Sub Agent overview
Beyond model configuration, Sub Agents define tools, structured outputs, and agent-to-agent relationships available to the Sub Agent.
| Parameter | Type | Required | Description |
| -------------------- | -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id` | string | Yes | Stable Sub Agent identifier used for consistency and persistence |
| `name` | string | Yes | Human-readable name for the Sub Agent |
| `prompt` | string | Yes | Detailed behavior guidelines and system prompt for the Sub Agent |
| `description` | string | No | Brief description of the Sub Agent's purpose and capabilities |
| `models` | object | No | Model configuration for this Sub Agent. See [Model Configuration](/typescript-sdk/models) |
| `stopWhen` | object | No | Stop conditions (`stepCountIs`). See [Configuring StopWhen](#configuring-stopwhen) |
| `canUse` | function | No | Returns the list of MCP/tools the Sub Agent can use. See [MCP Servers](/tutorials/mcp-servers/overview) for how to find or build MCP servers |
| `dataComponents` | array | No | Structured output components for rich, interactive responses. See [Data Components](/typescript-sdk/structured-outputs/data-components) |
| `artifactComponents` | array | No | Components for handling tool or Sub Agent outputs. See [Artifact Components](/typescript-sdk/structured-outputs/artifact-components) |
| `canTransferTo` | function | No | Function returning array of Sub Agents this Sub Agent can transfer to. See [Transfer Relationships](/typescript-sdk/agent-relationships#transfer-relationships) |
| `canDelegateTo` | function | No | Function returning array of Sub Agents this Sub Agent can delegate to. See [Delegation Relationships](/typescript-sdk/agent-relationships#delegation-relationships) |
### Tools & MCPs
Enable tools for a Sub Agent to perform actions like looking up information or calling external APIs.
Tools can be:
* **[MCP Servers](/typescript-sdk/tools/mcp-servers)** - Connect to external services and APIs using the Model Context Protocol
* **[Function Tools](/typescript-sdk/tools/function-tools)** - Custom JavaScript functions that execute directly in secure sandboxes
```typescript
import { subAgent, functionTool, mcpTool } from "@inkeep/agents-sdk";
const mySubAgent = subAgent({
id: "my-agent-id",
name: "My Sub Agent",
prompt: "Detailed behavior guidelines",
canUse: () => [
functionTool({
name: "get-current-time",
description: "Get the current time",
execute: async () => ({ time: new Date().toISOString() }),
}),
mcpTool({
id: "inkeep-kb-rag",
name: "Knowledge Base Search",
description: "Search the company knowledge base.",
serverUrl: "https://rag.inkeep.com/mcp",
}),
],
});
```
### Data components
Structured output components for rich, interactive responses. See [Data Components](/typescript-sdk/structured-outputs/data-components).
```typescript
import { z } from 'zod';
const mySubAgent = subAgent({
id: "my-agent-id",
name: "My Sub Agent",
prompt: "Detailed behavior guidelines",
dataComponents: [
{
id: "customer-info",
name: "CustomerInfo",
description: "Customer information display component",
props: z.object({
name: z.string().describe("Customer name"),
email: z.string().describe("Customer email"),
issue: z.string().describe("Customer issue description"),
}),
},
],
});
```
### Artifact components
Components for handling tool or Sub Agent outputs. See [Artifact Components](/typescript-sdk/structured-outputs/artifact-components).
```typescript
import { z } from 'zod';
import { preview } from '@inkeep/agents-core';
const mySubAgent = subAgent({
id: "my-agent-id",
name: "My Sub Agent",
prompt: "Detailed behavior guidelines",
artifactComponents: [
{
id: "customer-info",
name: "CustomerInfo",
description: "Customer information display component",
props: z.object({
name: preview(z.string().describe("Customer name")),
customer_info: z.string().describe("Customer information"),
}),
},
],
});
```
### Sub Agent relationships
Define other Sub Agents this Sub Agent can transfer control to or delegate tasks to.
```typescript
const mySubAgent = subAgent({
// ...
canTransferTo: () => [subAgent1],
canDelegateTo: () => [subAgent2],
});
```
As a next step, see [Sub Agent Relationships](/typescript-sdk/agent-relationships) to learn how to design transfer and delegation relationships between Sub Agents.
# CLI Observability with Langfuse
URL: /typescript-sdk/cli-observability
Track LLM operations during pull command with Langfuse
***
title: CLI Observability with Langfuse
description: Track LLM operations during pull command with Langfuse
-------------------------------------------------------------------
The Inkeep CLI includes built-in observability for tracking LLM operations during the `pull` command. This allows you to monitor costs, latency, and quality of AI-generated code across different LLM providers.
## Overview
When you run `inkeep pull`, the CLI uses LLMs to generate TypeScript files for your agents, tools, and components. With Langfuse integration enabled, you can:
* **Track token usage and costs** across Anthropic, OpenAI, and Google models
* **Monitor generation latency** to identify slow operations
* **View complete traces** of multi-file code generation
* **Analyze placeholder optimization** impact on token savings
* **Debug failed generations** with full context
## Setup
### 1. Create a Langfuse Account
Sign up for a free account at [cloud.langfuse.com](https://cloud.langfuse.com) (EU region) or [us.cloud.langfuse.com](https://us.cloud.langfuse.com) (US region).
### 2. Get API Keys
From your Langfuse dashboard:
1. Navigate to **Settings** → **API Keys**
2. Create a new API key pair
3. Copy both the **Secret Key** (`sk-lf-...`) and **Public Key** (`pk-lf-...`)
### 3. Configure Environment Variables
Add these variables to your `.env` file in your project root:
```bash
# Enable Langfuse tracing
LANGFUSE_ENABLED=true
# Your Langfuse credentials
LANGFUSE_SECRET_KEY=sk-lf-your-secret-key-here
LANGFUSE_PUBLIC_KEY=pk-lf-your-public-key-here
# Langfuse API URL (defaults to EU cloud)
LANGFUSE_BASEURL=https://cloud.langfuse.com # or https://us.cloud.langfuse.com for US
# Your LLM provider API keys (at least one required)
ANTHROPIC_API_KEY=your-anthropic-key
OPENAI_API_KEY=your-openai-key
GOOGLE_GENERATIVE_AI_API_KEY=your-google-key
```
### 4. Run Pull Command
Now when you run `inkeep pull`, all LLM operations will be traced to Langfuse:
```bash
inkeep pull --project my-agent-project
```
## Viewing Traces
### In Langfuse Dashboard
1. Go to your [Langfuse dashboard](https://cloud.langfuse.com)
2. Navigate to **Traces**
3. You'll see traces for each file generation operation
### Trace Metadata
Each trace includes rich metadata:
| Field | Description | Example |
| ------------------ | ---------------------------- | --------------------------------- |
| `fileType` | Type of file being generated | `agent`, `tool`, `data_component` |
| `placeholderCount` | Number of placeholders used | `5` |
| `promptSize` | Size of prompt in characters | `15234` |
| `model` | LLM model used | `claude-sonnet-4-5` |
### Example Trace Structure
```
Service: inkeep-agents-cli
├── generate-agent-file
│ ├── Model: claude-sonnet-4-5
│ ├── Tokens: 12,543 input / 3,421 output
│ ├── Duration: 8.3s
│ └── Metadata:
│ ├── fileType: agent
│ ├── placeholderCount: 12
│ └── promptSize: 25,891 chars
```
## Monitoring Strategies
### Track Costs by Provider
Compare costs across different LLM providers:
1. Filter traces by model in Langfuse
2. View cumulative costs in the **Usage** dashboard
3. Identify cost-saving opportunities
### Optimize Generation Time
Find slow generation steps:
1. Sort traces by duration
2. Check if complex agents need longer timeouts
3. Consider using faster models for simpler files
### Analyze Token Savings
Monitor placeholder optimization impact:
1. Look at `placeholderCount` metadata
2. Higher counts = more token savings
3. Useful for understanding efficiency gains
## Troubleshooting
### Traces Not Appearing
**Check if Langfuse is enabled:**
```bash
# Should output: true
echo $LANGFUSE_ENABLED
```
**Verify API keys are set:**
```bash
# Should show your keys (without exposing them)
env | grep LANGFUSE
```
**Check for errors:**
```bash
# Run with debug logging
DEBUG=* inkeep pull --project my-project
```
### Missing Metadata
If traces appear but lack metadata:
1. Ensure you're using the latest CLI version
2. Check that file type context is being passed correctly
3. Report issues on [GitHub](https://github.com/anthropics/claude-code/issues)
## Privacy Considerations
### What Data is Sent to Langfuse
* **Prompt content**: The full prompts sent to LLMs (includes your project data)
* **Generated code**: The TypeScript code generated by LLMs
* **Model metadata**: Model names, token counts, timings
* **File metadata**: File types, sizes, placeholder counts
### What is NOT Sent
* **Your API keys**: LLM provider keys are never sent to Langfuse
* **Other environment variables**: Only Langfuse-specific vars are used
### Self-Hosted Option
For complete control over your data, you can self-host Langfuse:
```bash
# Use your self-hosted instance
LANGFUSE_BASEURL=https://langfuse.your-domain.com
```
See [Langfuse self-hosting docs](https://langfuse.com/docs/deployment/self-host) for details.
## Best Practices
1. **Enable for development**: Keep tracing on during development to catch issues early
2. **Disable in CI/CD**: Turn off for automated builds to avoid unnecessary traces
3. **Review weekly**: Check Langfuse dashboard weekly to monitor costs and performance
4. **Set budgets**: Configure spending alerts in your LLM provider dashboards
## Related Documentation
* [SignOz Usage](/typescript-sdk/signoz-usage) - OpenTelemetry tracing for runtime operations
* [Langfuse Usage](/typescript-sdk/langfuse-usage) - Langfuse integration for agent runtime
* [CLI Reference](/typescript-sdk/cli-reference) - Complete CLI command reference
# CLI Reference
URL: /typescript-sdk/cli-reference
Complete reference for the Inkeep CLI commands
***
title: CLI Reference
description: Complete reference for the Inkeep CLI commands
icon: "LuTerminal"
------------------
## Overview
The Inkeep CLI is the primary tool for interacting with the Inkeep Agent Framework. It allows you to push Agent configurations and interact with your multi-agent system.
## Installation
```bash
# Install the CLI globally
npm install -g @inkeep/agents-cli
# Install the dashboard package (for visual agents orchestration)
npm install @inkeep/agents-manage-ui
```
## Global Options
All commands support the following global options:
* `--version` - Display CLI version
* `--help` - Display help for a command
## Commands
### `inkeep init`
Initialize a new Inkeep configuration file in your project.
```bash
inkeep init [path]
```
**Options:**
* `--no-interactive` - Skip interactive path selection
* `--config ` - Path to use as template for new configuration
**Examples:**
```bash
# Interactive initialization
inkeep init
# Initialize in specific directory
inkeep init ./my-project
# Non-interactive mode
inkeep init --no-interactive
# Use specific config as template
inkeep init --config ./template-config.ts
```
### `inkeep push`
**Primary use case:** Push a project containing Agent configurations to your server. This command deploys your entire multi-agent project, including all Agents, Sub Agents, and tools.
```bash
inkeep push
```
**Options:**
* `--project ` - Project ID or path to project directory
* `--env ` - Load environment-specific credentials from `environments/.env.ts`
* `--config ` - Override config file path (bypasses automatic config discovery)
* `--tenant-id ` - Override tenant ID
* `--agents-manage-api-url ` - Override the management API URL from config
* `--agents-run-api-url ` - Override agents run API URL
* `--json` - Generate project data as JSON file instead of pushing to server
**Examples:**
```bash
# Push project from current directory
inkeep push
# Push specific project directory
inkeep push --project ./my-project
# Push with development environment credentials
inkeep push --env development
# Generate project JSON without pushing
inkeep push --json
# Override tenant ID
inkeep push --tenant-id my-tenant
# Override API URLs
inkeep push --agents-manage-api-url https://api.example.com
inkeep push --agents-run-api-url https://run.example.com
# Use specific config file
inkeep push --config ./custom-config/inkeep.config.ts
```
**Environment Credentials:**
The `--env` flag loads environment-specific credentials when pushing your project. This will look for files like `environments/development.env.ts` or `environments/production.env.ts` in your project directory and load the credential configurations defined there.
**Example environment file:**
```typescript
// environments/development.env.ts
import { CredentialStoreType } from "@inkeep/agents-core";
import { registerEnvironmentSettings } from "@inkeep/agents-sdk";
export const development = registerEnvironmentSettings({
credentials: {
"api-key-dev": {
id: "api-key-dev",
type: CredentialStoreType.memory,
credentialStoreId: "memory-default",
retrievalParams: {
key: "API_KEY_DEV",
},
},
},
});
```
#### Project Discovery and Structure
The `inkeep push` command follows this discovery process:
1. **Config File Discovery**: Searches for `inkeep.config.ts` using this pattern:
* Starts from current working directory
* Traverses **upward** through parent directories until found
* Can be overridden by providing a path to the config file with the `--config` flag
2. **Workspace Structure**: Expects this directory layout:
```
workspace-root/
├── package.json # Workspace package.json
├── tsconfig.json # Workspace TypeScript config
├── inkeep.config.ts # Inkeep configuration file
├── my-project/ # Individual project directory
│ ├── index.ts # Project entry point
│ ├── agents/ # Agent definitions
│ │ └── *.ts
│ ├── tools/ # Tool definitions
│ │ └── *.ts
│ ├── data-components/ # Data component definitions
│ │ └── *.ts
│ └── environments/ # Environment-specific configs
│ ├── development.env.ts
│ └── production.env.ts
└── another-project/ # Additional projects
└── index.ts
```
3. **Resource Compilation**: Automatically discovers and compiles:
* All project directories containing `index.ts`
* All TypeScript files within each project directory
* Categorizes files by type (agents, Sub Agents, tools, data components)
* Resolves dependencies and relationships within each project
#### Push Behavior
When pushing, the CLI:
* Finds and loads configuration from `inkeep.config.ts` at workspace root
* Discovers all project directories containing `index.ts`
* Applies environment-specific settings if `--env` is specified
* Compiles all project resources defined in each project's `index.ts`
* Validates Sub Agent relationships and tool configurations across all projects
* Deploys all projects to the management API
* Prints deployment summary with resource counts per project
### `inkeep pull`
Pull project configuration from the server and update all TypeScript files in your local project using LLM generation.
```bash
inkeep pull
```
**Options:**
* `--project ` - Project ID to pull (or path to project directory). If in project directory, validates against local project ID.
* `--config ` - Path to configuration file
* `--env ` - Environment file to generate (development, staging, production). Defaults to development
* `--json` - Output project data as JSON instead of generating files
* `--debug` - Enable debug logging
* `--verbose` - Enable verbose logging
* `--force` - Force regeneration even if no changes detected
* `--introspect` - Completely regenerate all files from scratch (no comparison needed)
**Smart Project Detection:**
The pull command intelligently handles different scenarios:
1. **Project Directory Detection**: If your current directory contains an `index.ts` file that exports a project, the command automatically uses that project's ID
2. **Project ID Validation**: If you specify `--project` while in a project directory, it validates that the ID matches your local project
3. **Subdirectory Creation**: When not in a project directory, creates a new subdirectory named after the project ID
**`--project` Flag Behavior:**
The `--project` flag has dual functionality:
* **Directory Path**: If the value points to a directory containing `index.ts`, it uses that directory
* **Project ID**: If the value doesn't match a valid directory path, it treats it as a project ID
**Pull Modes:**
| Scenario | Command | Behavior |
| ------------------------ | -------------------------------------- | ---------------------------------------------------------------- |
| In project directory | `inkeep pull` | ✅ Automatically detects project, pulls to current directory |
| In project directory | `inkeep pull --project ` | ✅ Validates ID matches local project, pulls to current directory |
| In project directory | `inkeep pull --project ` | ❌ Error: Project ID doesn't match local project |
| Not in project directory | `inkeep pull` | ❌ Error: Requires --project flag |
| Not in project directory | `inkeep pull --project ` | ✅ Creates `/` subdirectory with project files |
**How it Works:**
The pull command discovers and updates all TypeScript files in your project based on the latest configuration from the server:
1. **File Discovery**: Recursively finds all `.ts` files in your project (excluding `environments/` and `node_modules/`)
2. **Smart Categorization**: Categorizes files as index, agents, Sub Agents, tools, or other files
3. **Context-Aware Updates**: Updates each file with relevant context from the server:
* **Agent files**: Updated with specific agent data
* **Sub Agent files**: Updated with specific Sub Agent configurations
* **Tool files**: Updated with specific tool definitions
* **Other files**: Updated with full project context
4. **LLM Generation**: Uses AI to maintain code structure while updating with latest data
#### TypeScript Updates (Default)
By default, the pull command updates your existing TypeScript files using LLM generation:
1. **Context Preservation**: Maintains your existing code structure and patterns
2. **Selective Updates**: Only updates relevant parts based on server configuration changes
3. **File-Specific Context**: Each file type receives appropriate context (Agents get Agent data, Sub Agents get Sub Agent data, etc.)
**Examples:**
```bash
# Directory-aware pull: Automatically detects project from current directory
cd my-project # Directory contains index.ts with project export
inkeep pull # Pulls to current directory, no subdirectory created
# Validate project ID while in project directory
cd my-project # Directory contains index.ts
inkeep pull --project my-project # Validates ID matches, pulls to current directory
# Error case: Wrong project ID in project directory
cd my-project # Directory contains index.ts with different project ID
inkeep pull --project different-project # ERROR: Project ID mismatch
# Pull when NOT in a project directory (requires --project)
cd ~/projects
inkeep pull # ERROR: Requires --project flag
# Pull specific project to new subdirectory
cd ~/projects
inkeep pull --project my-project # Creates ./my-project/ subdirectory
# Save project data as JSON file instead of updating files
inkeep pull --json
# Enable debug logging
inkeep pull --debug
# Enable verbose logging
inkeep pull --verbose
# Force regeneration even if no changes detected
inkeep pull --force
# Completely regenerate all files from scratch
inkeep pull --introspect
# Generate environment-specific credentials
inkeep pull --env production
# Use specific config file
inkeep pull --config ./custom-config/inkeep.config.ts
```
#### Model Configuration
The `inkeep pull` command automatically selects the best available model for LLM generation based on your API keys:
1. **Anthropic Claude** (if `ANTHROPIC_API_KEY` is set): `claude-sonnet-4-5`
2. **OpenAI GPT** (if `OPENAI_API_KEY` is set): `gpt-5.1`
3. **Google Gemini** (if `GOOGLE_GENERATIVE_AI_API_KEY` is set): `gemini-2.5-flash`
The models are used for intelligent content merging when updating modified components, ensuring your local customizations are preserved while incorporating upstream changes.
#### Validation Process
The `inkeep pull` command includes a two-stage validation process to ensure generated TypeScript files accurately represent your backend configuration:
**1. Basic File Verification**
* Checks that all expected files exist (index.ts, agent files, tool files, component files)
* Verifies file naming conventions match (kebab-case)
* Ensures project export is present in index.ts
**2. Round-Trip Validation** *(New in v0.24.0)*
* Loads the generated TypeScript using the same logic as `inkeep push`
* Serializes it back to JSON format
* Compares the serialized JSON with the original backend data
* Reports any differences found
This round-trip validation ensures:
* ✅ Generated TypeScript can be successfully loaded and imported
* ✅ The serialization logic (TS → JSON) works correctly
* ✅ Generated files will work with `inkeep push` without errors
* ✅ No data loss or corruption during the pull process
**Validation Output:**
```bash
✓ Basic file verification passed
✓ Round-trip validation passed - generated TS matches backend data
```
**If validation fails:**
The CLI will display specific differences between the generated and expected data:
```bash
✗ Round-trip validation failed
❌ Round-trip validation errors:
The generated TypeScript does not serialize back to match the original backend data.
• Value mismatch at agents.my-agent.name: "Original Name" vs "Generated Name"
• Missing tool in generated: tool-id
⚠️ This indicates an issue with LLM generation or schema mappings.
The generated files may not work correctly with `inkeep push`.
```
**TypeScript generation fails:**
* Ensure your network connectivity and API endpoints are correct
* Check that your model provider credentials (if required by backend) are set up
* Try using `--json` flag as a fallback to get the raw project data
**Validation errors during pull:**
* The generated TypeScript may have syntax errors or missing dependencies
* Check the generated file manually for obvious issues
* Try pulling as JSON first to verify the source data: `inkeep pull --json`
* If round-trip validation fails, report the issue with the error details
### `inkeep list-agents`
List all available agents for a specific project.
```bash
inkeep list-agents --project
```
**Options:**
* `--project ` - **Required.** Project ID to list agents for
* `--tenant-id ` - Tenant ID
* `--agents-manage-api-url ` - Agents manage API URL
* `--config ` - Path to configuration file
* `--config-file-path ` - Path to configuration file (deprecated, use --config)
**Examples:**
```bash
# List agents for a specific project
inkeep list-agents --project my-project
# List agents using a specific config file
inkeep list-agents --project my-project --config ./inkeep.config.ts
# Override tenant and API URL
inkeep list-agents --project my-project --tenant-id my-tenant --agents-manage-api-url https://api.example.com
```
### `inkeep dev`
Start the Inkeep dashboard server, build for production, or export the Next.js project.
> **Note:** This command requires `@inkeep/agents-manage-ui` to be installed for visual agents orchestration.
```bash
inkeep dev
```
**Options:**
* `--port ` - Port to run the server on (default: 3000)
* `--host ` - Host to bind the server to (default: localhost)
* `--build` - Build the Dashboard UI for production (packages standalone build)
* `--export` - Export the Next.js project source files
* `--output-dir ` - Output directory for build files (default: ./inkeep-dev)
* `--path` - Output the path to the Dashboard UI
**Examples:**
```bash
# Start development server
inkeep dev
# Start on custom port and host
inkeep dev --port 3001 --host 0.0.0.0
# Build for production (packages standalone build)
inkeep dev --build --output-dir ./build
# Export Next.js project source files
inkeep dev --export --output-dir ./my-dashboard
# Get dashboard path for deployment
DASHBOARD_PATH=$(inkeep dev --path)
echo "Dashboard built at: $DASHBOARD_PATH"
# Use with Vercel
vercel --cwd $(inkeep dev --path) -Q .vercel build
# Use with Docker
docker build -t inkeep-dashboard $(inkeep dev --path)
# Use with other deployment tools
rsync -av $(inkeep dev --path)/ user@server:/var/www/dashboard/
```
### `inkeep config`
Manage Inkeep configuration values.
**Subcommands:**
#### `inkeep config get [key]`
Get configuration value(s).
```bash
inkeep config get [key]
```
**Options:**
* `--config ` - Path to configuration file
* `--config-file-path ` - Path to configuration file (deprecated, use --config)
**Examples:**
```bash
# Get all config values
inkeep config get
# Get specific value
inkeep config get tenantId
```
#### `inkeep config set `
Set a configuration value.
```bash
inkeep config set
```
**Options:**
* `--config ` - Path to configuration file
* `--config-file-path ` - Path to configuration file (deprecated, use --config)
**Examples:**
```bash
inkeep config set tenantId my-tenant-id
inkeep config set apiUrl http://localhost:3002
```
#### `inkeep config list`
List all configuration values.
```bash
inkeep config list
```
**Options:**
* `--config ` - Path to configuration file
* `--config-file-path ` - Path to configuration file (deprecated, use --config)
### `inkeep add`
Pull a template project or MCP from the [Inkeep Agents Cookbook](https://github.com/inkeep/agents/tree/main/agents-cookbook).
```bash
inkeep add [options]
```
**Options:**
* `--project ` - Add a project template
* `--mcp ` - Add a custom MCP server template for common use cases (adds server code to your project)
* `--target-path ` - Target path to add the template to
* `--config ` - Path to configuration file
**Examples:**
```bash
# List available templates (both project and MCP)
inkeep add
# Add a project template
inkeep add --project activities-planner
# Add project template to specific path
inkeep add --project activities-planner --target-path ./examples
# Add a custom MCP server template (auto-detects apps/mcp/app directory)
inkeep add --mcp zendesk
# Add MCP server template to specific path
inkeep add --mcp zendesk --target-path ./apps/mcp/app
# Using specific config file
inkeep add --project activities-planner --config ./my-config.ts
```
**Behavior:**
* When adding an MCP server template without `--target-path`, the CLI automatically searches for an `apps/mcp/app` directory in your project
* If no app directory is found, you'll be prompted to confirm whether to add to the current directory
* Project templates are added to the current directory or specified `--target-path`
* Model configurations are automatically injected based on available API keys in your environment (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, or `GOOGLE_GENERATIVE_AI_API_KEY`)
### `inkeep update`
Update the Inkeep CLI to the latest version from npm.
```bash
inkeep update
```
**Options:**
* `--check` - Check for updates without installing
* `--force` - Force update even if already on latest version
**How it Works:**
The update command automatically:
1. **Detects Package Manager**: Identifies which package manager (npm, pnpm, bun, or yarn) was used to install the CLI globally
2. **Checks Version**: Compares your current version with the latest available on npm
3. **Updates CLI**: Executes the appropriate update command for your package manager
4. **Displays Changelog**: Shows a link to the changelog for release notes
**Examples:**
```bash
# Check if an update is available (no installation)
inkeep update --check
# Update to latest version (with confirmation prompt)
inkeep update
# Force reinstall current version
inkeep update --force
# Skip confirmation prompt (useful for CI/CD)
inkeep update --force
```
**Output Example:**
```
📦 Version Information:
• Current version: 0.22.3
• Latest version: 0.23.0
📖 Changelog:
• https://github.com/inkeep/agents/blob/main/agents-cli/CHANGELOG.md
🔍 Detected package manager: pnpm
✅ Updated to version 0.23.0
```
**Troubleshooting:**
If you encounter permission errors, try running with elevated permissions:
```bash
# For npm, pnpm, yarn
sudo inkeep update
# For bun
sudo -E bun add -g @inkeep/agents-cli@latest
```
**Package Manager Detection:**
The CLI automatically detects which package manager you used by checking global package installations:
* npm: Checks `npm list -g @inkeep/agents-cli`
* pnpm: Checks `pnpm list -g @inkeep/agents-cli`
* bun: Checks `bun pm ls -g`
* yarn: Checks `yarn global list`
If automatic detection fails, the CLI will prompt you to select your package manager.
## Configuration File
The CLI uses a configuration file (typically `inkeep.config.ts`) to store settings:
```typescript
import { defineConfig } from "@inkeep/agents-cli/config";
export default defineConfig({
tenantId: "your-tenant-id",
agentsManageApiUrl: "http://localhost:3002",
agentsRunApiUrl: "http://localhost:3003",
});
```
### Configuration Priority
Effective resolution order:
1. Command-line flags (highest)
2. Environment variables (override config values)
3. `inkeep.config.ts` values
## Environment Variables
The CLI and SDK respect the following environment variables:
* `INKEEP_TENANT_ID` - Tenant identifier
* `INKEEP_AGENTS_MANAGE_API_URL` - Management API base URL
* `INKEEP_AGENTS_RUN_API_URL` - Run API base URL
* `INKEEP_ENV` - Environment name for credentials loading during `inkeep push`
* `INKEEP_AGENTS_MANAGE_API_BYPASS_SECRET` - Optional bearer for Manage API (advanced)
* `INKEEP_AGENTS_RUN_API_BYPASS_SECRET` - Optional bearer for Run API (advanced)
## Troubleshooting
**Project Not Found:**
* Projects are automatically managed based on your tenantId
* `inkeep push` will create resources as needed
### Getting Help
For additional help with any command:
```bash
inkeep [command] --help
```
For issues or feature requests, visit: [GitHub Issues](https://github.com/inkeep/agents/issues)
# Context Fetchers
URL: /typescript-sdk/context-fetchers
Learn how to use context fetchers to fetch data from external sources and make it available to your agents
***
title: Context Fetchers
description: Learn how to use context fetchers to fetch data from external sources and make it available to your agents
icon: "LuCirclePlus"
--------------------
## Overview
Context fetchers allow you to embed real-time data from external APIs into your agent prompts. Instead of hardcoding information in your agent prompt, context fetchers dynamically retrieve fresh data for each conversation.
## Key Features
* **Dynamic data retrieval**: Fetch real-time data from APIs.
* **Dynamic Prompting**: Use dynamic data in your agent prompts
* **Headers integration**: Use request-specific parameters to customize data fetching.
* **Data transformation**: Transform API responses into the exact format your agent needs.
## Context Fetchers vs Tools
* **Context Fetchers**: Pre-populate agent prompts with dynamic data
* Run automatically before/during conversation startup
* Data becomes part of the agent's system prompt
* Perfect for: Personalized agent personas, dynamic agent guardrails
* Example Prompt: `You are an assistant for ${userContext.toTemplate('user.name')} and you work for ${userContext.toTemplate('user.organization')}`
* **Tools**: Enable agents to take actions or fetch data during conversations
* Called by the agent when needed during the conversation
* Agent decides when and how to use them
* Example Tool Usage: Agent calls a "send\_email" tool or "search\_database" tool
## Basic Usage
Let's create a simple context fetcher that retrieves user information:
```typescript
import { agent, subAgent } from "@inkeep/agents-sdk";
import { contextConfig, fetchDefinition, headers } from "@inkeep/agents-core";
import { z } from "zod";
// 1. Define a schema for headers validation. All header keys are converted to lowercase.
// In this example all incoming headers will be validated to make sure they include user_id and api_key.
const personalAgentHeaders = headers({
schema: z.object({
user_id: z.string(),
api_key: z.string(),
})
});
// 2. Create the fetcher with
const userFetcher = fetchDefinition({
id: "user-info",
name: "User Information",
trigger: "initialization", // Fetch only once when a conversation is started with the Agent. When set to "invocation", the fetch will be executed every time a request is made to the Agent.
fetchConfig: {
url: `https://api.example.com/users/${personalAgentHeaders.toTemplate('user_id')}`,
method: "GET",
headers: {
Authorization: `Bearer ${personalAgentHeaders.toTemplate('api_key')}`,
},
transform: "user", // Extract user from response, for example if the response is { "user": { "name": "John Doe", "email": "john.doe@example.com" } }, the transform will return the user object
},
responseSchema: z.object({
user: z.object({
name: z.string(),
email: z.string(),
}),
}), // Used to validate the result of the transformed api response.
defaultValue: "Unable to fetch user information",
});
// 3. Configure context
const personalAgentContext = contextConfig({
headers: personalAgentHeaders,
contextVariables: {
user: userFetcher,
},
});
// 4. Create and use the Sub Agent
const personalAssistant = subAgent({
id: "personal-assistant",
name: "Personal Assistant",
description: "A personalized AI assistant",
prompt: `Hello ${personalAgentContext.toTemplate('user.name')}! I'm your personal assistant.`,
});
// Initialize the Agent
export const myAgent = agent({
id: "personal-agent",
name: "Personal Assistant Agent",
defaultSubAgent: personalAssistant,
subAgents: () => [personalAssistant],
contextConfig: personalAgentContext,
});
```
## Using Context Variables
Context variables can be used in your agent prompts using JSONPath template syntax `{{contextVariableKey.field_name}}`.
Use the context config's `toTemplate()` method for type-safe templating with autocomplete and validation.
```typescript
const personalGraphContext = contextConfig({
headers: personalGraphHeaders,
contextVariables: {
user: userFetcher,
},
});
const personalAgent = subAgent({
id: "personal-agent",
name: "Personal Assistant",
description: "A personalized AI assistant",
prompt: `Hello ${personalGraphContext.toTemplate('user.name')}! I'm your personal assistant.`,
});
```
Context variables are resolved using [JSONPath notation](https://jsonpath.com).
## Data transformation
The `transform` property on fetch definitions lets you extract exactly what you need from API responses using JSONPath notation:
```typescript
// API returns: { "user": { "profile": { "displayName": "John Doe" } } }
transform: "user.profile.displayName"; // Result: "John Doe"
// API returns: { "items": [{ "name": "First Item" }, { "name": "Second Item" }] }
transform: "items[0].name"; // Result: "First Item"
```
## Best Practices
1. **Use Appropriate Triggers**
* `initialization`: Use when data rarely changes
* `invocation`: Use for frequently changing data
2. **Handle Errors Gracefully**
* Always provide a `defaultValue`
* Use appropriate response schemas
## Related documentation
* [Headers](/typescript-sdk/headers) - Learn how to pass dynamic context to your agents via HTTP headers
# Data Operations
URL: /typescript-sdk/data-operations
Learn about data operations emitted by agents and how to use the x-emit-operations header to control their visibility.
***
title: Data Operations
sidebarTitle: Data Operations
description: Learn about data operations emitted by agents and how to use the x-emit-operations header to control their visibility.
icon: LuActivity
keywords: data operations, emit operations, debugging, agent events, x-emit-operations header, agent monitoring
---------------------------------------------------------------------------------------------------------------
## Overview
Data operations are detailed, real-time events that provide visibility into what agents are doing during execution. They include agent reasoning, tool executions, transfers, delegations, and artifact creation. By default, these operations are hidden from end users to keep the interface clean, but they can be enabled for debugging and monitoring purposes.
## The x-emit-operations Header
The `x-emit-operations` header controls whether data operations are included in the response stream. When set to `true`, the system will emit detailed operational events alongside the regular response content.
### Usage
```bash
curl -N \
-X POST "http://localhost:3003/api/chat" \
-H "Authorization: Bearer $INKEEP_API_KEY" \
-H "Content-Type: application/json" \
-H "x-emit-operations: true" \
-d '{
"messages": [
{ "role": "user", "content": "What can you do?" }
],
"conversationId": "chat-1234"
}'
```
### CLI Usage
In the CLI, you can toggle data operations using the `operations` command:
```bash
# Start a chat session
inkeep chat
# Toggle data operations on/off
> operations
🔧 Emit operations: ON
Data operations will be shown during responses.
> operations
🔧 Emit operations: OFF
Data operations are hidden.
```
## Data Operation Types
### Agent Events
#### `agent_generate`
Emitted when an agent generates content (text or structured data).
```json
{
"type": "data-operation",
"data": {
"type": "agent_generate",
"label": "Agent search-agent generating response",
"details": {
"timestamp": 1726247200000,
"agentId": "search-agent",
"data": {
"parts": [
{
"type": "text",
"content": "I found 5 relevant documents..."
}
],
"generationType": "text_generation"
}
}
}
}
```
#### `agent_reasoning`
Emitted when an agent is reasoning through a request or planning its approach.
```json
{
"type": "data-operation",
"data": {
"type": "agent_reasoning",
"label": "Agent search-agent reasoning through request",
"details": {
"timestamp": 1726247200000,
"agentId": "search-agent",
"data": {
"parts": [
{
"type": "text",
"content": "I need to search for information about..."
}
]
}
}
}
}
```
### Tool Execution Events
#### `tool_call`
Emitted when an agent starts calling a tool or function.
```json
{
"type": "data-operation",
"data": {
"type": "tool_call",
"label": "Tool call: search_documents",
"details": {
"timestamp": 1726247200000,
"agentId": "search-agent",
"data": {
"toolName": "search_documents",
"args": {
"query": "machine learning best practices",
"limit": 10
},
"toolCallId": "call_abc123",
"toolId": "tool_xyz789"
}
}
}
}
```
#### `tool_result`
Emitted when a tool execution completes (success or failure).
```json
{
"type": "data-operation",
"data": {
"type": "tool_result",
"label": "Tool result: search_documents",
"details": {
"timestamp": 1726247200000,
"agentId": "search-agent",
"data": {
"toolName": "search_documents",
"result": {
"documents": [
{
"title": "ML Best Practices Guide",
"url": "/docs/ml-guide",
"relevance": 0.95
}
]
},
"toolCallId": "call_abc123",
"toolId": "tool_xyz789",
"duration": 1250
}
}
}
}
```
**Error Example:**
```json
{
"type": "data-operation",
"data": {
"type": "tool_result",
"label": "Tool error: search_documents",
"details": {
"timestamp": 1726247200000,
"agentId": "search-agent",
"data": {
"toolName": "search_documents",
"result": null,
"toolCallId": "call_abc123",
"toolId": "tool_xyz789",
"duration": 500,
"error": "API rate limit exceeded"
}
}
}
}
```
### Agent Interaction Events
#### `transfer`
Emitted when control is transferred from one agent to another.
```json
{
"type": "data-operation",
"data": {
"type": "transfer",
"label": "Agent transfer: search-agent → analysis-agent",
"details": {
"timestamp": 1726247200000,
"agentId": "search-agent",
"data": {
"fromSubAgent": "search-agent",
"targetAgent": "analysis-agent",
"reason": "Specialized analysis required",
"context": {
"searchResults": "...",
"userQuery": "..."
}
}
}
}
}
```
#### `delegation_sent`
Emitted when an agent delegates a task to another agent.
```json
{
"type": "data-operation",
"data": {
"type": "delegation_sent",
"label": "Task delegated: coordinator-agent → search-agent",
"details": {
"timestamp": 1726247200000,
"agentId": "coordinator-agent",
"data": {
"delegationId": "deleg_xyz789",
"fromSubAgent": "coordinator-agent",
"targetAgent": "search-agent",
"taskDescription": "Search for information about machine learning",
"context": {
"priority": "high",
"deadline": "2024-01-15T10:00:00Z"
}
}
}
}
}
```
#### `delegation_returned`
Emitted when a delegated task is completed and returned.
```json
{
"type": "data-operation",
"data": {
"type": "delegation_returned",
"label": "Task completed: search-agent → coordinator-agent",
"details": {
"timestamp": 1726247200000,
"agentId": "search-agent",
"data": {
"delegationId": "deleg_xyz789",
"fromSubAgent": "search-agent",
"targetAgent": "coordinator-agent",
"result": {
"status": "completed",
"documents": [...],
"summary": "Found 5 relevant documents"
}
}
}
}
}
```
### Artifact Events
#### `artifact_saved`
Emitted when an agent creates or saves an artifact (document, chart, file, etc.).
```json
{
"type": "data-operation",
"data": {
"type": "artifact_saved",
"label": "Artifact saved: chart",
"details": {
"timestamp": 1726247200000,
"agentId": "analysis-agent",
"data": {
"artifactId": "art_123456",
"taskId": "task_789",
"toolCallId": "tool_abc123",
"artifactType": "chart",
"summaryData": {
"title": "Sales Performance Q4 2023",
"type": "bar_chart"
},
"fullData": {
"chartData": [...],
"config": {...}
},
"metadata": {
"createdBy": "analysis-agent",
"version": "1.0"
}
}
}
}
}
```
## System Events
### `agent_initializing`
Emitted when the agent runtime is starting up.
```json
{
"type": "data-operation",
"data": {
"type": "agent_initializing",
"details": {
"sessionId": "session_abc123",
"agentId": "graph_xyz789"
}
}
}
```
### `completion`
Emitted when an agent completes its task.
```json
{
"type": "data-operation",
"data": {
"type": "completion",
"details": {
"agent": "search-agent",
"iteration": 1
}
}
}
```
### `error`
Emitted when an error occurs during execution.
```json
{
"type": "data-operation",
"data": {
"type": "error",
"message": "Tool execution failed: API rate limit exceeded",
"agent": "search-agent",
"severity": "error",
"code": "RATE_LIMIT_EXCEEDED",
"timestamp": 1726247200000
}
}
```
## Example: Complete Request with Data Operations
Here's a complete example showing a request with data operations enabled:
```bash
curl -N \
-X POST "http://localhost:3003/api/chat" \
-H "Authorization: Bearer $INKEEP_API_KEY" \
-H "Content-Type: application/json" \
-H "x-emit-operations: true" \
-d '{
"messages": [
{ "role": "user", "content": "Create a sales report for Q4" }
],
"conversationId": "chat-1234"
}'
```
**Response Stream:**
```text
data: {"type":"agent_initializing","details":{"sessionId":"session_abc123","agentId":"graph_xyz789"}}
data: {"type":"data-operation","data":{"type":"agent_reasoning","label":"Agent coordinator-agent reasoning through request","details":{"timestamp":1726247200000,"agentId":"coordinator-agent","data":{"parts":[{"type":"text","content":"I need to create a sales report for Q4. This will require gathering data and generating a chart."}]}}}}
data: {"type":"data-operation","data":{"type":"tool_call","label":"Tool call: get_sales_data","details":{"timestamp":1726247200000,"agentId":"coordinator-agent","data":{"toolName":"get_sales_data","args":{"quarter":"Q4","year":"2023"},"toolCallId":"call_abc123","toolId":"tool_xyz789"}}}}
data: {"type":"data-operation","data":{"type":"tool_result","label":"Tool result: get_sales_data","details":{"timestamp":1726247200000,"agentId":"coordinator-agent","data":{"toolName":"get_sales_data","result":{"sales":[...]},"toolCallId":"call_abc123","toolId":"tool_xyz789","duration":850}}}}
data: {"type":"data-artifact","data":{ ... }}
data: {"type":"data-operation","data":{"type":"artifact_saved","label":"Artifact saved: chart","details":{"timestamp":1726247200000,"agentId":"coordinator-agent","data":{"artifactId":"art_123456","artifactType":"chart","summaryData":{"title":"Q4 Sales Report"}}}}}
data: {"type":"text-start","id":"1726247200-abc123"}
data: {"type":"text-delta","id":"1726247200-abc123","delta":"I've created a comprehensive Q4 sales report..."}
data: {"type":"text-end","id":"1726247200-abc123"}
data: {"type":"completion","details":{"agent":"coordinator-agent","iteration":1}}
```
This provides complete visibility into the agent's execution process, from initialization through reasoning, tool execution, artifact creation, and final response generation.
# Add External Agents to your Agent
URL: /typescript-sdk/external-agents
Learn how to configure and use external agents using the A2A protocol
***
title: Add External Agents to your Agent
sidebarTitle: External Agents
description: Learn how to configure and use external agents using the A2A protocol
icon: "LuGlobe"
---------------
External agents let you integrate agents built outside of Inkeep (using other frameworks or platforms) into your Agent. They communicate over the A2A (Agent‑to‑Agent) protocol so your Inkeep sub-agents can delegate tasks to them as if they were native. Note that Inkeep Agents are available via an [A2A endpoint](/talk-to-your-agents/a2a) themselves and used from other platforms.
Learn more about A2A:
* A2A overview on the Google Developers Blog: [A2A — a new era of agent interoperability](https://developers.googleblog.com/en/a2a-a-new-era-of-agent-interoperability/)
* A2A protocol site: [a2a.how](https://a2a.how/)
Examples platforms that expose Agents in A2A-format:
| Platform | Type | Description |
| ----------------------------------------------------------------------------------------------------------------------------- | ------------ | ------------------------------------------------------------------- |
| [LangGraph](https://docs.langchain.com/langgraph-platform/server-a2a) | Native | Built-in A2A endpoint & Agent Card for graph agents. |
| [Google Agent Development Kit (ADK)](https://google.github.io/adk-docs/a2a/) | Native | Official guide to build agents that expose/consume A2A. |
| [Microsoft Semantic Kernel](https://devblogs.microsoft.com/foundry/semantic-kernel-a2a-integration/) | Native | “SK now speaks A2A” with sample to expose compliant agents. |
| [Pydantic AI](https://ai.pydantic.dev/a2a/) | Native | Convenience method to publish a Pydantic AI agent as an A2A server. |
| [AWS Strands Agents SDK](https://strandsagents.com/latest/documentation/docs/user-guide/concepts/multi-agent/agent-to-agent/) | Native | A2A support in Strands for cross‑platform agent communication. |
| [CrewAI](https://codelabs.developers.google.com/intro-a2a-purchasing-concierge) | With Adapter | Use the A2A Python SDK to serve a CrewAI agent over A2A. |
| [LlamaIndex](https://a2aprotocol.ai/blog/a2a-samples-llama-index-file-chat-openrouter) | With Adapter | Example Workflows app exposed via A2A (agent + card). |
Any agent that exposes an A2A‑compatible HTTP endpoint can be integrated by providing its `baseUrl` plus headers/auth (static or dynamic).
## Creating an External Agent
Every external agent needs a unique identifier, name, description, base URL for A2A communication, and optional authentication configuration:
```typescript
import { externalAgent } from "@inkeep/agents-sdk";
const technicalSupportAgent = externalAgent({
id: "technical-support-agent",
name: "Technical Support Team",
description: "External technical support specialists for complex issues",
baseUrl: "https://api.example.com/agents/technical-support", // A2A endpoint
});
```
## External Agent Relationships
Agents can be configured to delegate tasks to external agents.
```typescript
import { subAgent, agent } from "@inkeep/agents-sdk";
import { myExternalAgent } from "./external-agents/exernal-agent-example";
// Define the customer support sub-agent with delegation capabilities
const supportSubAgent = subAgent({
id: "support-agent",
name: "Customer Support Sub-Agent",
description: "Handles customer inquiries and escalates technical issues",
prompt: `You are a customer support sub-agent that handles general customer inquiries.`,
canDelegateTo: () => [myExternalAgent],
});
// Create the customer support agent with external agent capabilities
export const supportAgent = agent({
id: "customer-support-agent",
name: "Customer Support System",
description: "Handles customer inquiries and escalates to technical teams when needed",
defaultSubAgent: supportSubAgent,
subAgents: () => [supportSubAgent],
});
```
## External Agent Options
Configure authentication by providing a [credential reference](/typescript-sdk/tools/credentials).
```typescript
const myExternalAgent = externalAgent({
// Required
id: "external-support-agent",
name: "External Support Agent", // Human-readable agent name
description: "External AI agent for specialized support", // Agent's purpose
baseUrl: "https://api.example.com/agents/support", // A2A endpoint URL
// Optional - Credential Reference
credentialReference: myCredentialReference,
});
```
When delegating to an external agent, you can specify headers to include with every request to the external agent.
These headers can be dynamic variables that are [resolved at runtime](/typescript-sdk/headers).
```typescript
const supportSubAgent = subAgent({
id: "support-agent",
name: "Customer Support Sub-Agent",
description: "Handles customer inquiries and escalates technical issues",
prompt: `You are a customer support sub-agent that handles general customer inquiries.`,
canDelegateTo: () => [myExternalAgent.with({ headers: { Authorization: "Bearer {{headers.Authorization}}" } })],
});
```
| Parameter | Type | Required | Description |
| --------------------- | ------------------- | -------- | --------------------------------------------------------------------------------------------------------------------- |
| `id` | string | Yes | Stable agent identifier used for consistency and persistence |
| `name` | string | Yes | Human-readable name for the external agent |
| `description` | string | Yes | Brief description of the agent's purpose and capabilities |
| `baseUrl` | string | Yes | The A2A endpoint URL where the external agent can be reached |
| `credentialReference` | CredentialReference | No | Reference to dynamic credentials for authentication. See [Credentials](/typescript-sdk/tools/credentials) for details |
# Headers
URL: /typescript-sdk/headers
Pass dynamic context to your Agents via HTTP headers for personalized interactions
***
title: Headers
sidebarTitle: Headers
description: Pass dynamic context to your Agents via HTTP headers for personalized interactions
icon: LuBoxes
keywords: headers, context fetchers, prompt variables, personalization
----------------------------------------------------------------------
## Overview
Headers allow you to pass request-specific values (like user IDs, authentication tokens, or organization metadata) to your Agent at runtime via HTTP headers. These values are validated, cached per conversation, and made available throughout your Agent system for:
* **Context Fetchers**: Dynamic data retrieval based on request values
* **External Tools**: Authentication and personalization for API calls
* **Agent Prompts**: Personalized responses using context variables
## Passing context via headers
Include context values as HTTP headers when calling your agent API. These headers are validated against your configured schema and cached for the conversation.
```bash
curl -N \
-X POST "http://localhost:3003/api/chat" \
-H "Authorization: Bearer $INKEEP_API_KEY" \
-H "user_id: u_123" \
-H "auth_token: t_abc" \
-H "org_name: Acme Corp" \
-H "Content-Type: application/json" \
-d '{
"messages": [ { "role": "user", "content": "What can you help me with?" } ],
"conversationId": "conv-123"
}'
```
Header keys are normalized to lowercase. Define them as lowercase in your schema and reference them as lowercase in templates.
## Configuring headers
Define a schema for your headers and configure how it's used in your agent.
You must include the headers schema in your context config.
```typescript
import { z } from "zod";
import { agent, subAgent } from "@inkeep/agents-sdk";
import { contextConfig, fetchDefinition, headers } from '@inkeep/agents-core';
// Define schema for expected headers (use lowercase keys)
const personalAgentHeaders = headers({
schema: z.object({
user_id: z.string(),
auth_token: z.string(),
org_name: z.string().optional()
});
});
// Create a context fetcher that uses header values with type-safe templating
const userFetcher = fetchDefinition({
id: "user-info",
name: "User Information",
trigger: "initialization",
fetchConfig: {
url: `https://api.example.com/users/${personalAgentHeaders.toTemplate('user_id')}`,
method: "GET",
headers: {
Authorization: `Bearer ${personalAgentHeaders.toTemplate('auth_token')}`,
},
transform: "user", // Extract user from response, for example if the response is { "user": { "name": "John Doe", "email": "john.doe@example.com" } }, the transform will return the user object
},
responseSchema: z.object({
user: z.object({
name: z.string(),
email: z.string(),
}),
}),
defaultValue: "Guest User"
});
// Configure context for your agent
const personalAgentContext = contextConfig({
headers: personalAgentHeaders,
contextVariables: {
user: userFetcher,
},
});
// Create a Sub Agent that uses context variables
const personalAssistant = subAgent({
id: "personal-assistant",
name: "Personal Assistant",
description: "Personalized AI assistant",
prompt: `You are a helpful assistant for ${personalAgentContext.toTemplate('user.name')} from ${personalAgentHeaders.toTemplate('org_name')}.
User ID: ${personalAgentHeaders.toTemplate('user_id')}
Provide personalized assistance based on their context.`,
});
// Attach context to your Agent
const myAgent = agent({
id: "personal-agent",
name: "Personal Assistant Agent",
defaultSubAgent: personalAssistant,
subAgents: () => [personalAssistant],
contextConfig: personalAgentContext,
});
```
## How it works
**Validation**: Headers are validated against your configured schema when a request arrives
**Caching**: Validated context is cached per conversation for reuse across multiple interactions
**Reuse**: Subsequent requests with the same `conversationId` automatically use cached context values
**Updates**: Provide new header values to update the context for an ongoing conversation
Context values persist across conversation turns. To update them, send new header values with the same conversation ID.
## Using headers in your agents
Header values can be used in your agent prompts and fetch definitions using JSONPath template syntax `{{headers.field_name}}`.
You can use the headers schema's `toTemplate()` method for type-safe templating with autocomplete and validation.
### In Context Fetchers
Use header values to fetch dynamic data from external APIs:
```typescript
// Define schema for expected headers (use lowercase keys)
const personalAgentHeaders = headers({
schema: z.object({
user_id: z.string(),
auth_token: z.string(),
org_name: z.string().optional()
});
});
const userDataFetcher = fetchDefinition({
id: "user-data",
name: "User Data",
fetchConfig: {
url: `https://api.example.com/users/${personalAgentHeaders.toTemplate('user_id')}/profile`,
headers: {
Authorization: `Bearer ${personalAgentHeaders.toTemplate('auth_token')}`,
"X-Organization": personalAgentHeaders.toTemplate('org_name')
},
body: {
includePreferences: true,
userId: personalAgentHeaders.toTemplate('user_id')
}
},
responseSchema: z.object({
name: z.string(),
preferences: z.record(z.unknown())
})
});
// Configure context for your Agent
// You must include the headers schema and fetchers in your context config.
const personalAgentContext = contextConfig({
headers: personalAgentHeaders,
contextVariables: {
user: userFetcher,
},
});
```
### In Agent Prompts
Reference context directly in agent prompts for personalization using the context config's template method:
```typescript
// Create context config with both headers and fetchers
const userContext = contextConfig({
headers: requestHeaders,
contextVariables: {
userName: userDataFetcher,
},
});
const assistantAgent = subAgent({
prompt: `You are an assistant for ${userContext.toTemplate('userName')} from ${requestHeaders.toTemplate('org_name')}.
User context:
- ID: ${requestHeaders.toTemplate('user_id')}
- Organization: ${requestHeaders.toTemplate('org_name')}
Provide help tailored to their organization's needs.`
});
```
### In External Tools
Configure external agents or MCP servers with dynamic headers using the headers schema:
```typescript
// Define schema for expected headers (use lowercase keys)
const personalAgentHeaders = headers({
schema: z.object({
user_id: z.string(),
auth_token: z.string(),
org_name: z.string().optional()
});
});
// Configure external agent
const externalAgent = externalAgent({
id: "external-service",
baseUrl: "https://external.api.com",
headers: {
Authorization: `Bearer ${personalAgentHeaders.toTemplate('auth_token')}`,
"X-User-Context": personalAgentHeaders.toTemplate('user_id'),
"X-Org": personalAgentHeaders.toTemplate('org_name')
}
});
// Configure context for your Agent with your headers schema.
const personalAgentContext = contextConfig({
headers: personalAgentHeaders,
});
```
## Best practices
* **Use lowercase keys**: Always define schema properties in lowercase and reference them as lowercase in templates
* **Validate early**: Test your schema configuration with sample headers before deploying
* **Cache wisely**: Remember that context persists per conversation - design accordingly
* **Secure sensitive data**: For long-lived secrets, use the [Credentials](/typescript-sdk/tools/credentials) system instead of headers
* **Keep it minimal**: Only include context values that are actually needed by your agents
## Common use cases
### Multi-tenant applications
Pass tenant-specific configuration to customize agent behavior per customer:
```typescript
// Headers
"tenant_id: acme-corp"
"tenant_plan: enterprise"
"tenant_features: advanced-analytics,custom-branding"
```
### User authentication
Provide user identity and session information for personalized interactions:
```typescript
// Headers
"user_id: user_123"
"user_role: admin"
"session_token: sk_live_..."
```
### API gateway integration
Forward headers from your API gateway for consistent authentication:
```typescript
// Headers
"x-api-key: your-api-key"
"x-request-id: req_abc123"
"x-client-version: 2.0.0"
```
## Troubleshooting
### Invalid headers errors
If you receive a 400 error about invalid headers:
1. Verify your schema matches the headers you're sending
2. Ensure all header keys are lowercase
3. Check that required fields are present
4. Validate the data types match your schema
### Context not persisting
If context values aren't available in subsequent requests:
1. Ensure you're using the same `conversationId` across requests
2. Verify headers are being sent correctly
3. Check that your context config is properly attached to the Agent
## Related documentation
* [Context Fetchers](/typescript-sdk/context-fetchers) - Learn about fetching and caching external data
* [External Agents](/typescript-sdk/external-agents) - Configure external agent integrations
* [Credentials](/typescript-sdk/tools/credentials) - Manage secure credentials for your Agents
# Using Langfuse for LLM Observability
URL: /typescript-sdk/langfuse-usage
Complete guide to using Langfuse for LLM observability, tracing, and analytics in the Inkeep Agent Framework
***
title: Using Langfuse for LLM Observability
sidebarTitle: Langfuse Usage
description: Complete guide to using Langfuse for LLM observability, tracing, and analytics in the Inkeep Agent Framework
keywords: Langfuse, LLM observability, tracing, OpenTelemetry, AI monitoring, token usage, model analytics
icon: "brand/Langfuse"
----------------------
Langfuse is an open-source LLM engineering platform that provides specialized observability for AI applications, including token usage tracking, model performance analytics, and detailed LLM interaction tracing.
## Quick Start
### 1. Setup Langfuse Account
First, create a Langfuse account and get your API keys:
1. **Sign up** at [Langfuse Cloud](https://cloud.langfuse.com)
2. **Create a new project** in your Langfuse dashboard
3. **Get your API keys** from the project settings:
* Public Key: `pk-lf-xxxxxxxxxx`
* Secret Key: `sk-lf-xxxxxxxxxx`
### 2. Configure Langfuse
To integrate Langfuse with your Inkeep Agent Framework instrumentation, you need to modify your instrumentation file to include the Langfuse span processor.
Replace the default setup with a custom NodeSDK configuration:
Set your environment variables:
```bash
LANGFUSE_PUBLIC_KEY=pk-lf-xxxxxxxxxx
LANGFUSE_SECRET_KEY=sk-lf-xxxxxxxxxx
LANGFUSE_BASE_URL=https://us.cloud.langfuse.com
```
Update your instrumentation file:
```typescript
import {
defaultSpanProcessors,
defaultContextManager,
defaultResource,
defaultTextMapPropagator,
defaultInstrumentations,
} from "@inkeep/agents-run-api/instrumentation";
import { NodeSDK } from "@opentelemetry/sdk-node";
import { LangfuseSpanProcessor } from "@langfuse/otel";
export const defaultSDK = new NodeSDK({
resource: defaultResource,
contextManager: defaultContextManager,
textMapPropagator: defaultTextMapPropagator,
spanProcessors: [...defaultSpanProcessors, new LangfuseSpanProcessor()],
instrumentations: defaultInstrumentations,
});
defaultSDK.start();
```
Make sure to install the required dependencies in your run API directory:
`bash cd apps/run-api pnpm add @opentelemetry/sdk-node @langfuse/otel `
#### What This Configuration Does
* **Preserves all default instrumentation**: Uses the same resource, context manager, propagator, and instrumentations as the default setup
* **Adds Langfuse span processor**: Extends the default span processors with Langfuse's processor for specialized LLM observability
* **Maintains compatibility**: Your existing traces will continue to work while adding Langfuse-specific features
## Dataset setup and execution
Use the [Inkeep Agent Cookbook](https://github.com/inkeep/agents/tree/main/agents-cookbook) which provides ready-to-use scripts for creating and running Langfuse dataset evaluations programmatically.
#### 1. Clone the Agents Repository
```bash
git clone https://github.com/inkeep/agents.git
cd agents/agents-cookbook/evals/langfuse-dataset-example
```
**Set up environment variables in a `.env` file:**
```bash
# Langfuse configuration (required for both scripts)
LANGFUSE_PUBLIC_KEY=your_langfuse_public_key
LANGFUSE_SECRET_KEY=your_langfuse_secret_key
LANGFUSE_BASE_URL=https://cloud.langfuse.com
# Chat API configuration (for dataset runner)
INKEEP_AGENTS_RUN_API_KEY=your_api_key
INKEEP_AGENTS_RUN_API_URL=your_chat_api_base_url
# Execution context (for dataset runner)
INKEEP_TENANT_ID=your_tenant_id
INKEEP_PROJECT_ID=your_project_id
INKEEP_AGENT_ID=your_agent_id
```
#### 2. Initialize Dataset with Sample Data
Run the basic Langfuse example to initialize a dataset with sample user messages:
```bash
pnpm run langfuse-init-example
```
This script will:
* Connect to your Langfuse project
* Create a new dataset called "inkeep-weather-example-dataset" with sample dataset items
#### 3. Run Dataset Items to Generate Traces
Run dataset items to generate traces that can be evaluated:
```bash
pnpm run langfuse-run-dataset
```
This script will:
* Read items from your Langfuse dataset
* Execute each item against your weather agent
* Generate the data needed for evaluation
## Running LLM Evaluations in Langfuse Dashboard
Langfuse provides a powerful web interface for running LLM evaluations without writing code. You can create datasets, set up evaluators, and run evaluations directly in the dashboard.
### Accessing the Evaluation Features
1. **Log into your Langfuse dashboard**: [https://cloud.langfuse.com](https://cloud.langfuse.com)
2. **Navigate to your project** where your agent traces are being collected
3. **Click "Evaluations"** in the left sidebar
4. **Click "Set up evaluator"** to begin creating evaluations
### Setting Up LLM-as-a-Judge Evaluators
#### Set Up Default Evaluation Model
Before creating evaluators, you need to configure a default LLM connection for evaluations:
**Setting up the LLM Connection:**
1. **Navigate to "Evaluator Library"** in your Langfuse dashboard
2. **Click "Set up"** next to "Default Evaluation Model"
3. **Configure the LLM connection**:
* **LLM Adapter**: Select your preferred provider
* **Provider Name**: Give it a descriptive name (e.g., "openai")
* **API Key**: Enter your OpenAI API key (stored encrypted)
* **Advanced Settings**: Configure base URL, model parameters if needed
4. **Click "Create connection"** to save
#### Navigate to Evaluator Setup
1. **Go to "Evaluations"** → **"Running Evaluators"**
2. **Click "Set up evaluator"** button
3. **You'll see two main steps**: "1. Select Evaluator" and "2. Run Evaluator"
#### Choose Your Evaluator Type
You have two main options:
## Option A: Langfuse Managed Evaluators
Langfuse provides a comprehensive catalog of **pre-built evaluators**
**To use a managed evaluator:**
1. **Browse the evaluator list** and find one that matches your needs
2. **Click on the evaluator** to see its description and criteria
3. **Click "Use Selected Evaluator"** button
#### Customizing Managed Evaluators for Dataset Runs
Once you've selected a managed evaluator, you can **edit it to target your dataset runs**. This is particularly useful for evaluating agent performance against known test cases.
### Example: Customizing a Helpfulness Evaluator
1. **Select the "Helpfulness" evaluator** from the managed list
2. Under **Target** select dataset runs
3. **Configure variable mapping**
* **{`{{input}}`}** → **Object**: Trace, **Object Variable**: Input
* **{`{{generation}}`}** → **Object**: Trace, **Object Variable**: Output
## Option B: Create Custom Evaluator
1. **Click "+ Create Custom Evaluator"** button
2. **Fill in evaluator details**:
* **Name**: Choose a descriptive name (e.g., "weather\_tool\_used")
* **Description**: Explain what this evaluator measures
* **Model**: Select evaluation model
* **Prompt**: Configure a custom prompt
### Example: Customizing a Weather Tool Evaluator
1. **Prompt**
```
You are an expert evaluator for an AI agent system.
Your task is to rate the correctness of tool usage on a scale from 0.0 to 1.0.
Instructions:
If the user’s question is not weather-related and the tool used is not get_weather_forecast, return 1.0.
If the user’s question is not weather-related and the tool is get_weather_forecast, return 0.0.
If the user’s question is weather-related, return 1.0 only if the tool used is get_weather_forecast; otherwise return 0.0.
Input:
User Question: {`{{input}}`}
Tool Used: {`{{tool_used}}`}
```
2. **Configure variable mapping**:
* **{`{{input}}`}** → **Object**: Trace, **Object Variable**: Input
* **{`{{tool_used}}`}** → **Object**: Span, **Object Name**: weather-forecaster.ai.toolCall, **Object Variable**: Metadata, **JsonPath**: $.attributes\["ai.toolCall.name"]
## Enable and Monitor
1. **Click "Enable Evaluator"** to start automatic evaluation
2. **Monitor evaluation progress** in the dashboard
3. **View evaluation results** as they complete
# Conversation Memory
URL: /typescript-sdk/memory
Understand how conversation history is managed and included in the context window for both main and delegated agents
***
title: Conversation Memory
sidebarTitle: Memory
description: Understand how conversation history is managed and included in the context window for both main and delegated agents
icon: "LuBrain"
keywords: memory, context window, conversation history, message limits, token limits, delegation, tool results
--------------------------------------------------------------------------------------------------------------
## Overview
Conversation memory determines how much of the conversation history is included in the context window when your Agent processes a new message. The Inkeep Agent Framework automatically manages conversation history to balance context retention with token efficiency, with specialized handling for delegated agents and tool results.
## What's Included in Memory
The conversation history now includes:
* **Chat messages**: User messages and agent responses
* **Tool results**: Results from tool executions, providing context about what actions were performed
* **Agent communications**: Messages exchanged between agents during transfers and delegations
## Default Limits
By default, the system includes conversation history using these limits:
* **50 messages**: Up to the 50 most recent messages from the conversation
* **8,000 tokens**: Maximum of 8,000 tokens from previous conversation messages
The 50-message and 8,000-token limits are the default values. The token limit can be adjusted via the `AGENTS_CONVERSATION_HISTORY_MAX_OUTPUT_TOKENS_DEFAULT` environment variable if needed.
## How It Works
**Message Retrieval**: The system retrieves up to 50 most recent messages from the conversation history
**Delegation Filtering**: Messages are filtered based on delegation context - delegated agents see their own tool results plus top-level conversation context
**Token Calculation**: Remaining messages are processed, calculating token count for each message
**Exclusion**: If the total token count exceeds 4,000 tokens, older messages are excluded from the context window
## Memory for Delegated Agents
When agents delegate tasks to other agents, memory is intelligently filtered:
### Main Agents
* See complete conversation history including all tool results
* Maintain full context of delegated actions and their results
### Delegated Agents
* See conversation history filtered to their delegation scope
* Receive tool results from:
* Their own tool executions
* Top-level (non-delegated) tool executions
* Cannot see tool results from unrelated delegations
This ensures delegated agents have sufficient context while preventing memory pollution from unrelated parallel delegations.
## Tool Results in Memory
Tool execution results are automatically included in conversation history, helping agents:
* Understand what actions have already been performed
* Avoid duplicate tool calls
* Build on previous results when transferring between agents
The tool results include both the input parameters and output results, formatted as:
```
## Tool: search_knowledge_base
**Input:**
{
"query": "API authentication methods"
}
**Output:**
{
"results": [...]
}
```
# Model Configuration
URL: /typescript-sdk/models
Configure AI models for your Agents and Sub Agents
***
title: Model Configuration
description: Configure AI models for your Agents and Sub Agents
icon: "LuSettings2"
-------------------
Configure models at **Project** (required), **Agent**, or **Sub Agent** levels. Settings inherit down the hierarchy.
## Configuration Hierarchy
You **must configure at least the base model** at the project level:
```typescript
// inkeep.config.ts
export default defineConfig({
models: {
base: {
model: "anthropic/claude-sonnet-4-5",
providerOptions: { temperature: 0.7, maxOutputTokens: 2048 }
}
}
});
```
Override at agent or sub agent level:
```typescript
const myAgent = agent({
models: {
base: { model: "openai/gpt-4.1" } // Override project default
}
});
const mySubAgent = subAgent({
models: {
structuredOutput: { model: "openai/gpt-4.1-mini" } // Override for JSON output
}
});
```
## Model Types
| Type | Purpose | Fallback |
| ------------------ | ----------------------------- | ----------------------------- |
| `base` | Text generation and reasoning | **Required at project level** |
| `structuredOutput` | JSON/structured output only | Falls back to `base` |
| `summarizer` | Summaries and status updates | Falls back to `base` |
## Supported Models
| Provider | Example Models | API Key |
| ---------------------------- | -------------------------------------------------------------------------------------------- | ------------------------------ |
| **Anthropic** | `anthropic/claude-sonnet-4-5` `anthropic/claude-haiku-4-5` | `ANTHROPIC_API_KEY` |
| **OpenAI** | `openai/gpt-4.1` `openai/gpt-4.1-mini` `openai/gpt-4.1-nano` `openai/gpt-5`\* | `OPENAI_API_KEY` |
| **Google** | `google/gemini-2.5-flash` `google/gemini-2.5-flash-lite` | `GOOGLE_GENERATIVE_AI_API_KEY` |
| **OpenRouter** | `openrouter/anthropic/claude-sonnet-4-0` `openrouter/meta-llama/llama-3.1-405b` | `OPENROUTER_API_KEY` |
| **Gateway** | `gateway/openai/gpt-4.1-mini` | `AI_GATEWAY_API_KEY` |
| **NVIDIA NIM** | `nim/nvidia/llama-3.3-nemotron-super-49b-v1.5` `nim/nvidia/nemotron-4-340b-instruct` | `NIM_API_KEY` |
| **Custom OpenAI-compatible** | `custom/my-custom-model` `custom/llama-3-custom` | `CUSTOM_LLM_API_KEY` |
\*`openai/gpt-5`, `openai/gpt-5-mini`, and `openai/gpt-5-nano` require a verified OpenAI organization. If your organization is not yet verified, these models will not be available.
### Pinned vs Unpinned Models
**Pinned models** include a specific date or version (e.g., `anthropic/claude-sonnet-4-20250514`) and always use that exact version.
**Unpinned models** use generic identifiers (e.g., `anthropic/claude-sonnet-4-5`) and let the provider choose the latest version, which may change over time as providers update their models.
```typescript
models: {
base: {
model: "anthropic/claude-sonnet-4-5", // Unpinned - provider chooses version
// vs
model: "anthropic/claude-sonnet-4-20250514" // Pinned - exact version
}
}
```
The TypeScript SDK also provides constants for common models:
```typescript
import { Models } from "@inkeep/agents-sdk";
models: {
base: {
model: Models.ANTHROPIC_CLAUDE_SONNET_4_5, // Type-safe constants
}
}
```
## Provider Options
Inkeep Agents supports all [Vercel AI SDK provider options](https://ai-sdk.dev/providers/ai-sdk-providers/).
### Complete Examples
**Basic configuration:**
```typescript
models: {
base: {
model: "anthropic/claude-sonnet-4-5",
providerOptions: {
maxOutputTokens: 4096,
temperature: 0.7,
topP: 0.95,
seed: 12345,
maxDuration: 30,
}
}
}
```
```json
{
"maxOutputTokens": 4096,
"temperature": 0.7,
"topP": 0.95,
"seed": 12345,
"maxDuration": 30
}
```
**OpenAI with reasoning:**
```typescript
models: {
base: {
model: "openai/o1-preview",
providerOptions: {
openai: { reasoningEffort: 'medium' }, // 'low' | 'medium' | 'high'
maxOutputTokens: 4096
}
}
}
```
```json
{
"openai": { "reasoningEffort": "medium" },
"maxOutputTokens": 4096
}
```
**Anthropic with thinking:**
```typescript
models: {
base: {
model: "anthropic/claude-sonnet-4-5",
providerOptions: {
anthropic: {
thinking: { type: 'enabled', budgetTokens: 8000 },
temperature: 0.5
}
}
}
}
```
```json
{
"anthropic": {
"thinking": { "type": "enabled", "budgetTokens": 8000 }
},
"temperature": 0.5
}
```
**Google with thinking:**
```typescript
models: {
base: {
model: "google/gemini-2.5-flash",
providerOptions: {
google: {
thinkingConfig: { thinkingBudget: 8192, includeThoughts: true }
},
temperature: 0.7
}
}
}
```
```json
{
"google": {
"thinkingConfig": { "thinkingBudget": 8192, "includeThoughts": true }
},
"temperature": 0.7
}
```
**Custom OpenAI-compatible provider:**
```typescript
models: {
base: {
model: "custom/my-custom-model",
providerOptions: {
baseURL: "https://api.example.com/v1", // Required
temperature: 0.7
}
}
}
```
```json
{
"baseUrl": "http://127.0.0.1:8090/v1",
"temperature": 0.7
}
```
Custom OpenAI-compatible providers **require** a base URL to be specified in `providerOptions.baseURL` or `providerOptions.baseUrl`. The `CUSTOM_LLM_API_KEY` environment variable will be automatically used for authentication if present.
## CLI Defaults
When using `inkeep init`, defaults are set based on your chosen provider:
| Provider | Base | Structured Output | Summarizer |
| ------------- | ------------------- | ----------------------- | ----------------------- |
| **Anthropic** | `claude-sonnet-4-5` | `claude-sonnet-4-5` | `claude-sonnet-4-5` |
| **OpenAI** | `gpt-4.1` | `gpt-4.1-mini` | `gpt-4.1-nano` |
| **Google** | `gemini-2.5-flash` | `gemini-2.5-flash-lite` | `gemini-2.5-flash-lite` |
# Project Management
URL: /typescript-sdk/project-management
Learn how to manage projects in the Inkeep Agent Framework
***
title: Project Management
description: Learn how to manage projects in the Inkeep Agent Framework
icon: "LuFolderOpen"
--------------------
<>
## Overview
Projects are the top-level organizational unit in your Inkeep workspace. Each project contains its own agents, sub agents, tools, data components, and environment configurations.
## Workspace structure
After following the [Quick Start](/get-started/quick-start) guide, your workspace will be organized with the following directory structure:
```
workspace-root/
├── package.json # Workspace package.json
├── .env # Workspace environment variables
├── src/
│ ├── inkeep.config.ts # Workspace configuration file
│ ├── projects/
│ │ ├── my-agent-project/
│ │ │ ├── index.ts
│ │ │ ├── agents/
│ │ │ │ ├── main-agent.ts
│ │ │ │ └── support-agent.ts
│ │ │ ├── tools/
│ │ │ │ ├── search-tool.ts
│ │ │ │ └── calculator-tool.ts
│ │ │ ├── data-components/
│ │ │ │ ├── user-profile.ts
│ │ │ │ └── product-catalog.ts
│ │ │ ├── external-agents/
│ │ │ │ ├── exernal-agent-example.ts
│ │ │ └── environments/
│ │ │ ├── index.ts
│ │ │ ├── development.env.ts
│ │ │ └── production.env.ts
│ │ └── another-project/ # Additional projects can coexist
│ │ ├── index.ts
│ │ └── ...
```
The `src/inkeep.config.ts` file defines workspace configuration for all projects. See [Workspace Configuration](/typescript-sdk/workspace-configuration) for details.
## Architecture
This project follows a workspace structure with the following services:
* **Agents Manage UI** (Port 3000): Web interface
* The agent framework visual builder. From the builder you can create, manage and visualize all your graphs.
* **Agents Manage API** (Port 3002): Agent configuration and management
* Handles entity management and configuration endpoints.
* **Agents Run API** (Port 3003): Agent execution and chat processing
* Handles agent communication. You can interact with your agents either over MCP from an MCP client or through our React UI components library
* **MCP Service** (Port 3006): Custom MCP servers
* Custom MCP servers for external tools and APIs. See [our guide](https://docs.inkeep.com/tutorials/mcp-servers/custom-mcp-servers#getting-started) for how to add MCP servers to your project.
## Project files and directories
### `index.ts`
The project entry point inside each project directory that exports your project definition:
```typescript file="src/projects/my-agent-project/index.ts"
// Located inside project directory (e.g., my-agent-project/index.ts)
import { project } from '@inkeep/agents-sdk';
import { mainAgent } from './agents/main-agent';
import { supportAgent } from './agents/support-agent';
import { searchTool } from './tools/search-tool';
import { calculatorTool } from './tools/calculator-tool';
import { userProfile } from './data-components/user-profile';
export const myProject = project({
id: 'my-agent-project',
name: 'My Agent Project',
description: 'A comprehensive multi-agent system',
subAgents: () => [mainAgent, supportAgent],
tools: () => [searchTool, calculatorTool],
dataComponents: () => [userProfile],
});
```
### `agents/`
Contains agent definitions. Each file typically exports one agent:
```typescript file="src/projects/my-agent-project/agents/customer-support.ts"
// agents/customer-support.ts
import { agent, subAgent } from '@inkeep/agents-sdk';
const routerSubAgent = subAgent({
id: 'support-router',
name: 'Support Router',
prompt: 'Route customer inquiries to appropriate specialists',
});
const billingSubAgent = subAgent({
id: 'billing-specialist',
name: 'Billing Specialist',
prompt: 'Handle billing and payment inquiries',
});
export const customerSupportAgent = agent({
defaultSubAgent: routerSubAgent,
subAgents: () => [routerSubAgent, billingSubAgent],
});
```
See [Agents & Sub Agents](https://docs.inkeep.com/typescript-sdk/agent-settings) for more information about creating and configuring agents and sub agents.
### `tools/`
Tool definitions that can be used by Sub Agents:
```typescript
// tools/database-query.ts
import { mcpTool } from '@inkeep/agents-sdk';
export const databaseQueryTool = mcpTool({
id: 'db-query',
name: 'Database Query Tool',
description: 'Execute SQL queries against the database',
inputSchema: {
type: 'object',
properties: {
query: { type: 'string' },
database: { type: 'string' }
}
},
// Tool implementation...
});
```
See [MCP Tools](https://docs.inkeep.com/typescript-sdk/tools/mcp-tools) and [Function Tools](https://docs.inkeep.com/typescript-sdk/tools/function-tools) for more information about creating and configuring MCP tools and function tools.
### `data-components/`
Data components for structured UI output:
```typescript
// data-components/customer-data.ts
import { dataComponent } from '@inkeep/agents-sdk';
import { z } from 'zod';
export const customerData = dataComponent({
id: 'customer-data',
name: 'Customer Information',
description: 'Customer profile and interaction history',
props: z.object({
customerId: z.string().describe("Customer ID"),
name: z.string().describe("Customer name"),
email: z.string().describe("Customer email"),
}),
});
```
See [Data Components](https://docs.inkeep.com/typescript-sdk/structured-outputs/data-components) for more information about creating and configuring data components.
### `external-agents/`
External agent definitions:
```typescript
import { externalAgent } from '@inkeep/agents-sdk';
export const exernalAgentExample = externalAgent({
id: 'exernal-agent-example',
name: 'Exernal Agent Example',
description: 'An example external agent',
baseUrl: 'https://api.example.com/agents/support',
credentialReference: myCredentialReference,
});
```
See [External Agents](https://docs.inkeep.com/typescript-sdk/external-agents) for more information about creating and configuring external agents.
### `environments/`
Environment-specific configurations for different deployment stages:
```typescript
// environments/production.env.ts
import { registerEnvironmentSettings } from '@inkeep/agents-sdk';
import { CredentialStoreType } from '@inkeep/agents-core';
export const production = registerEnvironmentSettings({
credentials: {
"openai-prod": {
id: "openai-prod",
type: CredentialStoreType.memory,
credentialStoreId: "memory-default",
retrievalParams: {
key: "OPENAI_API_KEY_PROD",
},
},
},
});
```
## How to add a new project
Use the `inkeep add` command to add template projects from the [Inkeep Agents Cookbook](https://github.com/inkeep/agents/tree/main/agents-cookbook/template-projects) to your workspace.
### Prerequisite
Ensure you have the [Inkeep CLI](/typescript-sdk/cli-reference) installed.
```bash
npm install -g @inkeep/agents-cli
```
### Step 1: Navigate to your projects directory
Navigate to the `src/projects` directory:
```bash
cd src/projects
```
### Step 2: List available templates
To see all available project templates, run `inkeep add` without any arguments:
```bash
inkeep add
```
This displays a list of available project templates you can add to your workspace.
### Step 3: Add a project template
Add a specific project template using the `--project` flag:
```bash
inkeep add --project docs-assistant
```
For new projects, we recommend starting with a simple project template like docs-assistant, which you can customize to your needs.
## Pushing changes to the Visual Builder
After making changes to your project code, use `inkeep push` to sync your local TypeScript project to the Visual Builder. This allows you to continue development using the Visual Builder's drag-and-drop interface.
### Prerequisite
Ensure you have the [Inkeep CLI](/typescript-sdk/cli-reference) installed.
```bash
npm install -g @inkeep/agents-cli
```
### Step 1: Navigate to your project directory
Change to the directory containing your project's `index.ts` file:
```bash
cd src/projects/my-agent-project
```
### Step 2: Push your project
Run the push command:
```bash
inkeep push
```
### Step 3: Verify in Visual Builder
After pushing, refresh your Visual Builder. Your project and all its agents, Sub Agents, tools, and data components will be available in the Visual Builder.
### Additional options
**Validate without pushing:**
To validate your project without actually pushing changes, use the `--json` flag:
```bash
inkeep push --json
```
## Pulling changes from the Visual Builder
When you make changes in the Visual Builder (such as updating prompts or modifying agent configurations), use `inkeep pull` to sync those changes back to your local TypeScript project.
### Prerequisite
The `inkeep pull` command in-part leverages AI to sync your TypeScript files to the state of your Visual Builder, so **at least one** of the below environment variables to be defined:
```txt .env
# Choose one:
ANTHROPIC_API_KEY=your_api_key_here
# or
OPENAI_API_KEY=your_api_key_here
# or
GOOGLE_API_KEY=your_api_key_here
```
The CLI prioritizes Anthropic → OpenAI → Google.
Here are the models used:
| Provider | Model(s) | Where to Get API Key |
| --------- | ------------------------------------- | --------------------------------------------------- |
| Anthropic | Claude Sonnet 4.5 (extended thinking) | [Anthropic Console](https://console.anthropic.com/) |
| OpenAI | GPT-5.1 | [OpenAI Platform](https://platform.openai.com/) |
| Google | Gemini 2.5 Flash | [Google AI Studio](https://ai.google.dev/) |
### Step 1: Navigate to your project directory
Change to the directory containing your project's `index.ts` file:
```bash
cd src/projects/my-agent-project
```
### Step 2: Pull changes from Visual Builder
Run the pull command:
```bash
inkeep pull
```
### Step 3: Verify the changes
Check your project files to see the updates. For example, if you changed an agent's prompt in the Visual Builder:
```bash
cat agents/my-agent.ts
```
The file should reflect the updated prompt from the Visual Builder.
See [CLI Reference](/typescript-sdk/cli-reference#inkeep-pull) for more information about the `inkeep pull` command.
## How to add a new MCP server
Use the `inkeep add` command to add custom MCP server templates from the [Inkeep Agents Cookbook](https://github.com/inkeep/agents/tree/main/agents-cookbook/template-mcps) to your workspace. These templates provide starter code for common MCP server integrations that you can customize and deploy.
### Prerequisite
Ensure you have the [Inkeep CLI](/typescript-sdk/cli-reference) installed.
```bash
npm install -g @inkeep/agents-cli
```
### Step 1: Navigate to your workspace root
Navigate to your workspace root directory (where your `package.json` is located):
```bash
cd /path/to/your/workspace
```
The CLI will automatically detect the `apps/mcp/app` directory in your workspace.
### Step 2: List available MCP templates
To see all available MCP server templates, run `inkeep add` without any arguments:
```bash
inkeep add
```
This displays both project templates and MCP server templates you can add to your workspace.
### Step 3: Add an MCP server template
Add a specific MCP server template using the `--mcp` flag:
```bash
inkeep add --mcp zendesk
```
The template will be added to `apps/mcp/app/[template-name]/mcp/route.ts` automatically.
### Step 4: Customize and register
The MCP server will be exposed at `http://localhost:3000/[template-name]/mcp`. Customize it with your API credentials and business logic, then register it as a tool using `mcpTool`:
```typescript
import { mcpTool } from '@inkeep/agents-sdk';
export const zendeskTool = mcpTool({
id: 'zendesk',
name: 'zendesk',
description: 'Zendesk API',
serverUrl: 'http://localhost:3000/zendesk/mcp',
});
```
See [MCP Tools](/typescript-sdk/tools/mcp-tools) for more information about registering MCP servers as tools.
## Deployment Guides
To build and run your own images you can follow the [Build a Custom Image](https://docs.inkeep.com/self-hosting/docker-build) docs.
This repostory contains a `docker-compose.yml` and template `Dockerfile` for each service:
* `Dockerfile.manage-ui`
* `Dockerfile.manage-api`
* `Dockerfile.run-ui`
* `Dockerfile.migrate`
To build and run:
```bash
docker compose build
docker compose up -d
```
### Deploy using official prebuilt images
* [Deploy to Vercel](https://docs.inkeep.com/self-hosting/vercel)
* [Docker (Local Dev)](https://docs.inkeep.com/self-hosting/docker-local)
* [GCP Compute Engine](https://docs.inkeep.com/self-hosting/gcp-compute-engine)
* [GCP Cloud Run](https://docs.inkeep.com/self-hosting/gcp-cloud-run)
* [AWS EC2](https://docs.inkeep.com/self-hosting/aws-ec2)
* [Hetzner](https://docs.inkeep.com/self-hosting/hetzner)
>
# Using SigNoz for Observability
URL: /typescript-sdk/signoz-usage
Complete guide to using SigNoz for observability, monitoring, tracing in the Inkeep Agent Framework
***
title: Using SigNoz for Observability
sidebarTitle: SigNoz Usage
description: Complete guide to using SigNoz for observability, monitoring, tracing in the Inkeep Agent Framework
keywords: SigNoz, observability, monitoring, tracing, OpenTelemetry, APM, metrics
icon: "brand/Signoz"
--------------------
SigNoz is a full-stack observability platform that provides distributed tracing so that you can track requests across multiple agents and services.
### Quick Start
Before using SigNoz, ensure it's properly set up and running. For setup instructions, see the [Quick Start](/get-started/traces) guide.
## Using SigNoz UI
The **Traces** page provides detailed request tracing:
#### Viewing Traces
The SigNoz traces interface provides comprehensive visibility into your agent operations:
The traces explorer shows:
* **Timestamp**: When each span occurred
* **Service Name**: The service that generated the span (e.g., `inkeep-agents-run-api`)
* **Operation Name**: Specific operations like `ai.generateObject`, `tls.connect`, `ai.toolCall`
* **Duration**: How long each operation took (in milliseconds)
* **HTTP Method**: For HTTP operations, shows the method (POST, GET, etc.)
* **Response Status Code**: HTTP status codes (200, 404, etc.)
Key features of the traces view:
* **Filtering Options**: Use the left sidebar to filter by duration, deployment environment, service name, and more
* **Time Range Selection**: Choose from preset ranges or custom time periods
* **Multiple Views**: Switch between List View, Traces, Time Series, and Table View
* **Real-time Updates**: Traces refresh automatically to show new data
* **Trace List**: Browse all traces with filtering options
* **Trace Details**: Drill down into individual traces
* **Span Timeline**: See the execution flow across agents
#### Filtering Traces
```
# Filter by service
service_name = "inkeep-agents-run-api"
# Filter by operation
operation = "agent.generate"
# Filter by status
status = "error"
# Filter by duration
duration > 1000ms
# Filter by custom attributes
agent.id = "customer-support-agent"
```
#### Analyzing Individual Traces
When you click on a specific trace from the list, you'll see the detailed trace view with a flamegraph visualization:
**Flamegraph Visualization:**
* **Horizontal Bars**: Each bar represents a span (operation) in your trace
* **Bar Width**: Proportional to the duration of the operation
* **Color Coding**:
* Blue bars: Successful operations
* Red bars: Operations with errors
**Key Information Displayed:**
* **Total Spans**: Total number of operations in this trace (e.g., 122)
* **Error Spans**: Number of spans that encountered errors (e.g., 19)
* **Trace Duration**: Total time for the entire trace (e.g., 5.2 mins)
* **Timestamp**: When the trace occurred
* **Service**: The primary service (e.g., `inkeep-agents-run-api`)
**Span Details Panel (Right Side):**
* **Span Name & ID**: Operation name and unique identifier
* **Timing**: Start time and duration
* **Service & Kind**: Which service and span type (Server, Client, etc.)
* **Status**: Success/error status code
* **Attributes, Events & Links**: Additional span metadata
**How to Use This View:**
1. **Identify Bottlenecks**: Look for the widest bars in the flamegraph - these represent the longest-running operations
2. **Find Errors**: Red bars indicate operations that failed - click on them to see error details
3. **Understand Flow**: Follow the vertical hierarchy to see how operations call each other
4. **Analyze Performance**: Use the timeline to see which operations run in parallel vs. sequentially
5. **Drill Down**: Click on any span to see detailed attributes, events, and error information
# Workspace Configuration
URL: /typescript-sdk/workspace-configuration
Learn how to configure your workspace
***
title: Workspace Configuration
description: Learn how to configure your workspace
icon: "LuSettings"
------------------
## Overview
The `inkeep.config.ts` file at the workspace root defines settings for all projects in this workspace. See [Project Management](/typescript-sdk/project-management#workspace-layout) for where this file should be placed.
```typescript
import { defineConfig } from '@inkeep/agents-cli/config';
import 'dotenv/config';
export default defineConfig({
tenantId: 'my-company',
agentsManageApi: {
url: 'http://localhost:3002',
apiKey: process.env.MANAGE_API_KEY, // Optional
},
agentsRunApi: {
url: 'http://localhost:3003',
apiKey: process.env.RUN_API_KEY, // Optional
},
outputDirectory: './output',
});
```
## Configuration hierarchy
One can override the settings in `inkeep.config.ts` by setting the following settings in this order (highest to lowest priority):
```mermaid
graph LR
A[CLI flags] --> B[Environment variables]
B --> C[Config file values]
C --> D[Built-in defaults]
style A fill:
style B fill:
style C fill:
style D fill:
```
### 1. CLI Flags
Command-line flags override all other settings:
```bash
# Override API URL
inkeep push --agents-manage-api-url https://api.production.com
# Override config file location
inkeep pull --config /path/to/custom.config.ts
```
### 2. Environment Variables
Environment variables override config file values:
```bash
# Set via environment
export INKEEP_TENANT_ID=staging-tenant
export INKEEP_AGENTS_MANAGE_API_URL=https://api.staging.com
export INKEEP_AGENTS_RUN_API_URL=https://run.staging.com
# Now CLI commands use these values
inkeep push
```
**Supported Environment Variables:**
| Variable | Config Equivalent | Description |
| ------------------------------ | -------------------- | ------------------ |
| `INKEEP_TENANT_ID` | `tenantId` | Tenant identifier |
| `INKEEP_AGENTS_MANAGE_API_URL` | `agentsManageApiUrl` | Management API URL |
| `INKEEP_AGENTS_RUN_API_URL` | `agentsRunApiUrl` | Runtime API URL |
### 3. Config File Values
Values explicitly set in your `inkeep.config.ts`:
```typescript
export default defineConfig({
tenantId: 'my-tenant',
agentsManageApi: {
url: 'http://localhost:3002',
},
agentsRunApi: {
url: 'http://localhost:3003',
},
});
```
### 4. Built-in Defaults
Default values used when not specified elsewhere:
```typescript
const defaults = {
agentsManageApiUrl: 'http://localhost:3002',
agentsRunApiUrl: 'http://localhost:3003',
};
```
## Working with multiple configurations
### Dynamic configuration
You can use environment-based logic in your workspace config:
```typescript
// inkeep.config.ts
import { defineConfig } from '@inkeep/agents-cli/config';
const isDevelopment = process.env.NODE_ENV === 'development';
export default defineConfig({
tenantId: process.env.TENANT_ID || 'default-tenant',
agentsManageApiUrl: isDevelopment
? 'http://localhost:3002'
: 'https://api.production.com',
});
```
### Multiple configuration files
For workspaces requiring different configurations:
```typescript
// inkeep.config.ts
export default defineConfig({
tenantId: 'production-tenant',
agentsManageApiUrl: 'https://api.production.com',
});
```
```typescript
// inkeep.dev.config.ts
export default defineConfig({
tenantId: 'dev-tenant',
agentsManageApiUrl: 'http://localhost:3002',
});
```
```bash
# Use development config (specify from any project directory)
inkeep push --config ../inkeep.dev.config.ts
# or with absolute path
inkeep push --config /path/to/workspace/inkeep.dev.config.ts
```
# JSON Schema guide for components
URL: /ui-components/json-schema-validation
Guide for writing valid JSON Schemas for data components and artifact components
***
title: JSON Schema guide for components
sidebarTitle: JSON Schemas
description: Guide for writing valid JSON Schemas for data components and artifact components
icon: LuFileCheck
keywords: JSON Schema, data components, artifact components, LLM compatibility
------------------------------------------------------------------------------
This guide shows you how to write valid JSON Schemas for your components. The framework validates these schemas to ensure they work properly with LLMs.
## Why validation matters
LLMs need clear, structured information to understand how to use your components. The validation ensures:
* All properties have descriptions (so the LLM knows what they're for)
* Required fields are clearly marked
* The schema structure is correct
## Data component props
When creating data components, your `props` field must be a valid JSON Schema:
### ✅ Valid example
```json
{
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "The title of the content item"
},
"url": {
"type": "string",
"description": "The URL where this content can be accessed"
},
"tags": {
"type": "array",
"description": "List of tags to categorize this content",
"items": {
"type": "string"
}
},
"priority": {
"type": "string",
"enum": ["low", "medium", "high"],
"description": "Priority level for this content item"
}
},
"required": ["title", "url"]
}
```
### ❌ Common mistakes
```json
{
// ❌ Missing "type": "object"
"properties": {
"title": {
"type": "string"
// ❌ Missing description
}
}
// ❌ Missing required array
}
```
## Artifact component schemas
Artifact components use a single unified schema called `props` with `inPreview` indicators.
### Unified props schema
Fields marked with `inPreview: true` appear in summary views, while all fields are stored in the database:
```json
{
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Title of the artifact",
"inPreview": true
},
"status": {
"type": "string",
"enum": ["draft", "published", "archived"],
"description": "Current status of the artifact",
"inPreview": true
},
"createdAt": {
"type": "string",
"format": "date-time",
"description": "When the artifact was created",
"inPreview": true
},
"content": {
"type": "string",
"description": "Main content of the artifact"
},
"metadata": {
"type": "object",
"description": "Additional metadata for the artifact",
"properties": {
"author": {
"type": "string",
"description": "Who created this artifact"
},
"version": {
"type": "string",
"description": "Version number of the artifact"
}
},
"required": ["author"]
},
"attachments": {
"type": "array",
"description": "Files attached to this artifact",
"items": {
"type": "object",
"properties": {
"filename": {
"type": "string",
"description": "Name of the attached file"
},
"url": {
"type": "string",
"description": "URL to download the file"
}
},
"required": ["filename", "url"]
}
}
},
"required": ["title", "status", "content"]
}
```
### Using Zod schemas with preview helpers
You can also use Zod schemas with the preview helper:
```typescript
import { z } from 'zod';
import { preview } from '@inkeep/agents-core/utils/schema-conversion';
const artifactSchema = z.object({
title: preview(z.string().describe("Title of the artifact")),
status: preview(z.enum(["draft", "published", "archived"]).describe("Current status")),
content: z.string().describe("Main content of the artifact"),
metadata: z.object({
author: z.string().describe("Who created this artifact"),
version: z.string().describe("Version number")
})
});
```
## Validation rules
The editor enforces these rules:
1. **Must be an object**: Top level must have `"type": "object"`
2. **Must have properties**: Include a `"properties"` object
3. **Must have required array**: Include a `"required"` array (even if empty)
4. **All properties need descriptions**: Every property must have a `"description"` field
### Quick template
Need a starting point? Click the "Template" button in the editor, or use this:
```json
{
"type": "object",
"properties": {
"example_property": {
"type": "string",
"description": "Description of what this property represents"
}
},
"required": ["example_property"]
}
```
## Common patterns
### Optional vs required
```json
{
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "User's full name"
},
"email": {
"type": "string",
"description": "User's email address (optional)"
}
},
"required": ["name"]
// email is optional since it's not in the required array
}
```
### Enums for fixed choices
```json
{
"type": "object",
"properties": {
"category": {
"type": "string",
"enum": ["work", "personal", "urgent"],
"description": "Category to organize this item"
}
},
"required": ["category"]
}
```
### Arrays with specific item types
```json
{
"type": "object",
"properties": {
"images": {
"type": "array",
"description": "List of image URLs for this item",
"items": {
"type": "string",
"format": "uri"
}
}
},
"required": ["images"]
}
```
That's it! The editor will guide you with real-time validation feedback as you type.
# Context Fetchers
URL: /visual-builder/context-fetchers
Learn how to use context fetchers to fetch data from external sources and make it available to your agents
***
title: Context Fetchers
sidebarTitle: Context Fetchers
description: Learn how to use context fetchers to fetch data from external sources and make it available to your agents
icon: "LuCirclePlus"
--------------------
## Overview
Context fetchers allow you to embed real-time data from external APIs into your agent prompts. Instead of hardcoding information in your agent prompt, context fetchers dynamically retrieve fresh data for each conversation.
## Key Features
* **Dynamic data retrieval**: Fetch real-time data from APIs.
* **Dynamic Prompting**: Use dynamic data in your agent prompts
* **Headers integration**: Use request-specific parameters to customize data fetching.
* **Data transformation**: Transform API responses into the exact format your agent needs.
## Context Fetchers vs Tools
* **Context Fetchers**: Pre-populate agent prompts with dynamic data
* Run automatically before/during conversation startup
* Data becomes part of the agent's system prompt
* Perfect for: Personalized agent personas, dynamic agent guardrails
* Example Prompt: `You are an assistant for {{user.name}} and you work for {{user.organization}}`
* **Tools**: Enable agents to take actions or fetch data during conversations
* Called by the agent when needed during the conversation
* Agent decides when and how to use them
* Example Tool Usage: Agent calls a "send\_email" tool or "search\_database" tool
## Basic Usage
1. Go to the Agents tab in the left sidebar. Then click on the agent you want to configure.
2. On the right pane scroll down to the "Context Variables" section.
3. Add your context variables in JSON format.
4. Click on the "Save" button.
## Defining Context Variables
The keys that you define in the Context Variables JSON object are used to reference fetched data in your agent prompts.
Each key in the JSON should map to a fetch definition with the following properties:
* **`id`** (required): Unique identifier for the fetch definition
* **`name`** (optional): Human-readable name for the fetch definition
* **`trigger`** (required): When to execute the fetch:
* `"initialization"`: Fetch only once when a conversation is started with the agent
* `"invocation"`: Fetch every time a request is made to the agent
* **`fetchConfig`** (required): HTTP request configuration:
* **`url`** (required): The API endpoint URL (supports template variables)
* **`method`** (optional): HTTP method - `GET`, `POST`, `PUT`, `DELETE`, or `PATCH` (defaults to `GET`)
* **`headers`** (optional): Object with string key-value pairs for HTTP headers
* **`body`** (optional): Request body for POST/PUT/PATCH requests
* **`transform`** (optional): JSONPath expression or JavaScript transform function to extract specific data from the response
* **`timeout`** (optional): Request timeout in milliseconds (defaults to 10000)
* **`responseSchema`** (optional): Valid JSON Schema object to validate the API response structure.
* **`defaultValue`** (optional): Default value to use if the fetch fails or returns no data
* **`credential`** (optional): Reference to stored credentials for authentication
Here is an example of a valid Context Variables JSON object:
```json
{
"userInfo": {
"id": "user-info",
"name": "User Information",
"trigger": "initialization",
"fetchConfig": {
"url": "https://api.example.com/users/{{headers.user_id}}",
"method": "GET",
"headers": {
"Authorization": "Bearer {{headers.api_key}}"
},
"transform": "user"
},
"responseSchema": {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"email": {
"type": "string"
}
},
},
"defaultValue": "Unable to fetch user information"
}
}
```
## Using Context Variables
Once you have defined your context variables, you can use them in your agent prompts.
1. Click on the agent you want to modify.
2. In the "Prompt" section, you can embed fetched data in the prompt using the key defined in the "Context Variables" section. Reference them using double curly braces `{{}}`.
Here is an example of an agent prompt using the context variable defined above:
```
You are a helpful assistant for {{userInfo.name}}.
```
# Related documentation
* [Headers](/visual-builder/headers) - Learn how to pass dynamic context to your agents via HTTP headers
# Headers
URL: /visual-builder/headers
Pass dynamic context to your agents via HTTP headers for personalized interactions
***
title: Headers
sidebarTitle: Headers
description: Pass dynamic context to your agents via HTTP headers for personalized interactions
icon: LuBoxes
keywords: headers, context fetchers, prompt variables, personalization
----------------------------------------------------------------------
## Overview
Headers allow you to pass request-specific values (like user IDs, authentication tokens, or organization metadata) to your agent at runtime via HTTP headers. These values are validated and made available throughout your agent system for:
* **Context Fetchers**: Dynamic data retrieval based on request values
* **External Tools**: Authentication and personalization for API calls
* **Agent Prompts**: Personalized responses using context variables
## Configuring Headers
1. Go to the Agents tab in the left sidebar. Then click on the agent you want to configure.
2. On the right pane scroll down to the "Headers schema" section.
3. Enter the schema in JSON Schema format.
4. Click on the "Save" button.
Here is an example of a valid headers schema:
```json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"userId": {
"type": "string"
}
},
"required": [
"userId"
],
"additionalProperties": {}
}
```
You can generate custom schemas using this [JSON Schema generator](https://transform.tools/json-to-json-schema).
## Sending Custom Headers
1. On your agent page, click on the **Try it** button in the top right corner.
2. Click on the "Custom headers" button in the top right corner.
3. Enter the custom headers in JSON format.
4. Click on the "Apply" button.
## Using Headers in Your Agent Prompts
1. Go to the Agents tab in the left sidebar. Then click on the agent you want to configure.
2. Either add a new agent or edit an existing agent by clicking on the agent you want to edit.
3. On the right pane scroll down to the "Prompt" section.
4. Use the double curly braces `{{}}` to reference the headers variables.
Here is an example of a valid prompt:
```text
You are a helpful assistant for {{headers.user_id}}!.
```
# Project Management
URL: /visual-builder/project-management
Learn how to create and manage projects in the Inkeep Agent Framework
***
title: Project Management
description: Learn how to create and manage projects in the Inkeep Agent Framework
icon: "LuFolder"
----------------
## Overview
Projects are the top-level organizational unit in the Inkeep Agent Framework. Each project contains its own agents, tools, and resources. This allows you to separate different applications or environments within a single tenant.
## Creating a Project
There are two ways to create a new project:
### Using the Project Dialog
When you have existing projects, you can create a new one using the "Create Project" button in the project switcher at the bottom of the sidebar.
### First Project Creation
If you don't have any projects yet, you'll be automatically redirected to the project creation page when you log in. You can also access it directly at `/{tenantId}/projects/new`.
## Project Fields
When creating a project, you'll need to provide:
* **Project ID**: A unique identifier for your project. This must:
* Start and end with lowercase alphanumeric characters
* May contain hyphens in the middle
* Cannot be changed after creation
* Examples: `my-project`, `production-v2`, `test-env1`
* **Project Name**: A friendly display name for your project (up to 100 characters)
* **Description**: A brief description of what the project is for (up to 500 characters)
## Project Structure
Each project can contain:
* **Agents**: Collections of AI agents that work together
* **API Keys**: Authentication keys for accessing your agents via API
* **MCP Servers**: Model Context Protocol servers for external tools
* **Data Components**: Reusable data structures for your agents
* **Artifact Components**: Reusable UI components for agent outputs
* **Credentials**: Secure storage for API keys and authentication tokens
## Project-Level Configuration
Projects can define default configurations that cascade down to all agents and Sub Agents within the project. This provides a consistent baseline while allowing specific overrides where needed.
### Model Settings
Define default models at the project level that all agents and Sub Agents will inherit:
```typescript
// Project configuration
{
id: "my-project",
name: "My AI Project",
models: {
base: {
model: "anthropic/claude-sonnet-4-5",
providerOptions: {
temperature: 0.7,
maxOutputTokens: 4096
}
},
structuredOutput: {
model: "openai/gpt-4.1-mini",
providerOptions: {
temperature: 0.1,
maxOutputTokens: 2048
}
},
summarizer: {
model: "openai/gpt-4.1-nano",
providerOptions: {
temperature: 0.3,
maxOutputTokens: 1024
}
}
}
}
```
### StopWhen Configuration
Configure default stopping conditions to prevent infinite loops:
```typescript
{
id: "my-project",
stopWhen: {
transferCountIs: 5, // Max transfers between Sub Agents per conversation
stepCountIs: 20 // Max tool calls + LLM responses per Sub Agent execution
}
}
```
## Configuration Inheritance
The framework uses a cascading inheritance system with specific rules for different configuration types:
### Model Inheritance - Partial Cascading
**Project** → **Agent** → **Sub Agent**
The framework supports **partial cascading**, meaning each level can override specific model types while inheriting others. This provides maximum flexibility while maintaining sensible defaults.
#### How Partial Cascading Works
Each model type (`base`, `structuredOutput`, `summarizer`) cascades independently:
```typescript
// Project Level - Sets defaults for all agents
Project: {
models: {
base: { model: "anthropic/claude-sonnet-4-5" },
structuredOutput: { model: "openai/gpt-4.1-mini" },
summarizer: { model: "openai/gpt-4.1-nano" }
}
}
// Agent Level - Partially overrides project defaults
Agent: {
models: {
base: { model: "openai/gpt-4.1" } // Override: use different base model
// structuredOutput: INHERITED from project (openai/gpt-4.1-mini)
// summarizer: INHERITED from project (openai/gpt-4.1-nano)
}
}
// Sub Agent Level - Can override any inherited model
Sub Agent: {
models: {
summarizer: { model: "anthropic/claude-haiku-4-5" } // Override: use faster summarizer
// base: INHERITED from Agent (openai/gpt-4.1)
// structuredOutput: INHERITED from project (openai/gpt-4.1-nano)
}
}
```
#### Final Resolution Example
In the above example, the Sub Agent ends up with:
* **base**: `gpt-4.1` (from Agent)
* **structuredOutput**: `gpt-4.1-mini` (from project)
* **summarizer**: `claude-3.5-haiku` (from Sub Agent)
#### Provider Options Override
When a model is overridden at any level, the entire configuration (including provider options) is replaced:
```typescript
// Project defines base model with options
Project: {
models: {
base: {
model: "claude-sonnet-4-0",
providerOptions: {
temperature: 0.7,
maxOutputTokens: 4096
}
}
}
}
// Agent completely overrides the base model settingsuration
Agent: {
models: {
base: {
model: "claude-sonnet-4-0", // Same model
providerOptions: {
temperature: 0.3, // New temperature
maxOutputTokens: 2048 // New maxOutputTokens - project maxOutputTokens is NOT inherited
}
}
}
}
```
#### Fallback to Base Model
**Important**: `structuredOutput` and `summarizer` only fall back to the `base` model when there's nothing to inherit from higher levels (project/agent).
#### System Defaults
**Supported Providers**: The framework supports Anthropic, OpenAI, and Google models.
**API Keys**: You need the appropriate API key for the provider you choose to use:
* `ANTHROPIC_API_KEY` for Anthropic models
* `OPENAI_API_KEY` for OpenAI models
* `GOOGLE_GENERATIVE_AI_API_KEY` for Google models
```typescript
// No higher-level defaults - fallback to base occurs
Project: {
// No models configured
}
Agent: {
// No models configured
}
Sub Agent: {
models: {
base: {
model: "gpt-4.1-2025-04-14",
providerOptions: {
temperature: 0.7,
maxOutputTokens: 2048
}
}
// No structuredOutput or summarizer specified
}
}
```
**Final Resolution with Fallback:**
* **base**: `gpt-4.1-2025-04-14` with specified provider options (from Agent)
* **structuredOutput**: `gpt-4.1-2025-04-14` with same provider options (falls back to Agent's base)
* **summarizer**: `gpt-4.1-2025-04-14` with same provider options (falls back to Agent's base)
**Contrast with Inheritance:**
```typescript
// Project has summarizer configured - inheritance takes priority
Project: {
models: {
summarizer: {
model: "gpt-4.1-mini";
}
}
}
Sub Agent: {
models: {
base: {
model: "gpt-4.1";
}
}
}
```
**Final Resolution with Inheritance:**
* **base**: `gpt-4.1` (from Sub Agent)
* **summarizer**: `gpt-4.1-mini` (inherited from project - NO fallback to Sub Agent's base)
* **structuredOutput**: Falls back to Sub Agent's base `gpt-4.1` (no inheritance available, so fallback occurs)
### StopWhen Inheritance
StopWhen settings inherit from Project → Agent → Sub Agent:
* **`transferCountIs`**: Project or Agent level
* **`stepCountIs`**: Project or Sub Agent level
```typescript
// Project sets defaults
Project: {
stopWhen: {
transferCountIs: 5, // Max transfers per conversation
stepCountIs: 15 // Max steps per Sub Agent
}
}
// Agent can override transfer limit, inherits step limit
Agent: {
stopWhen: {
transferCountIs: 8 // Override: allow more transfers in this Agent
// stepCountIs: 15 (inherited from project)
}
}
// Individual Sub Agent can override its own step limit
Sub Agent: {
stopWhen: {
stepCountIs: 25 // This Sub Agent can take more steps
// transferCountIs not applicable at Sub Agent level
}
}
```
## Switching Between Projects
Use the project switcher in the bottom left of the sidebar to quickly switch between projects. The switcher shows:
* The project name (or ID if no name is set)
* The project ID
* A brief description (if provided)
## API Access
Projects can be accessed programmatically via the CRUD API:
```typescript
// List all projects
GET /tenants/{tenantId}/crud/projects
// Get a specific project
GET /tenants/{tenantId}/crud/projects/{projectId}
// Create a new project
POST /tenants/{tenantId}/crud/projects
{
"id": "my-project",
"name": "My Project",
"description": "A project for my AI agents"
}
// Update a project
PATCH /tenants/{tenantId}/crud/projects/{projectId}
{
"name": "Updated Name",
"description": "Updated description"
}
// Delete a project
DELETE /tenants/{tenantId}/crud/projects/{projectId}
```
## Best Practices
1. **Use descriptive IDs**: Choose project IDs that clearly indicate their purpose (e.g., `customer-support`, `internal-tools`)
2. **Separate by environment**: Create different projects for development, staging, and production
3. **Document your projects**: Use the description field to explain what each project is for
4. **Organize by application**: Group related agents and tools within the same project
## Next Steps
After creating a project, you can:
* [Create your first Agent](/visual-builder/sub-agents)
* [Configure MCP servers for tools](/visual-builder/tools/mcp-servers)
* [Set up API keys for external access](/api-keys)
# Get started with the Visual Agent Builder
URL: /visual-builder/sub-agents
Create Agents with a No-Code Visual Agent Builder
***
title: Get started with the Visual Agent Builder
sidebarTitle: Agents & Sub Agents
description: Create Agents with a No-Code Visual Agent Builder
icon: "LuSpline"
----------------
## Overview
An Agent is the top-level entity you can chat and interact with in the Visual Builder.
An Agent is made up of one or more Sub Agents. The Sub Agents that make up an Agent can delegate or transfer control to each other, share context, or use tools to respond to a user or complete a task.
You can use the Visual Builder to add Sub Agents to an Agent, give Sub Agents tools, and connect Sub Agents with each other to establish their relationships.
## Creating your first Agent
1. Go to the Agents tab in the left sidebar. Then select "Create Agent".
2. Provide a name, prompt, and description.
### Agent Prompt
You can configure an Agent-level prompt that gets automatically added to all Sub Agents that make up the Agent. This provides consistent context and behavior guidelines so Sub Agents respond and act as one cohesive unit.
**Example uses:**
* Company-wide policies and tone guidelines
* Domain-specific context that applies to all sub-agents
* Consistent behavior rules across the sub-agent network
Once an Agent is created, you can always edit the prompt by:
1. Clicking on the **Agent Settings** button next to **Try it**
2. Modify your prompt in the "Agent Prompt" field
3. Click **Save**
## Default Sub Agent
When you create an Agent, it'll have a **Default Sub Agent** by default. This is the Sub Agent that first receives and processes a user message.
Configure its name and prompt, then click **Save**.
## Trying the Agent
To try the Agent, ensure it has at least one Sub Agent, then save the Agent by clicking the "Save changes" button in the top right corner.
Then, click the **Try it** button in the top right corner and type into the chat input.
## Adding tools
Tools are used to perform actions in the Agent. You can register MCP tools in the Visual Builder. See the [MCP Servers](/visual-builder/tools/mcp-servers) page to get started.
Once you have an MCP Server registered, you can add it to a Sub Agent by dragging and dropping the **MCP** block from the top left onto the Canvas.
To connect the tool to the Sub Agent, click the "+" icon at the top of the MCP block, then drag the connector to the Sub Agent. A line will appear, indicating that the tool is connected to the Sub Agent.
To delete a tool, click on the tool box and then hit the backspace key.
## Add other Sub Agents
When you have tasks that get more complex, you'll likely want to create more Sub Agents that are specialized in narrow tasks and have prompts and tools focused on their roles.
To create more Sub Agents:
1. Drag and drop a **Sub Agent** block from the top left toolbar onto the canvas.
2. Configure the Sub Agent with its own prompt and settings
3. Connect it to the parent Sub Agent by clicking the connector at the top of the Sub Agent box and dragging it to the main Sub Agent
When connected, a line will appear showing the relationship between the Sub Agents.
A few notes:
* To delete a Sub Agent, click on the Sub Agent box and then hit the backspace key.
* An Agent must have at least one Sub Agent. If you delete the default Sub Agent, add a new one before trying the Agent.
### Sub Agent configuration
The following are configurable options for the Sub Agent through the Visual Builder:
| Parameter | Type | Required | Description |
| --------------------- | ------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `name` | string | Yes | Human-readable name for the Sub Agent |
| `description` | string | No | Brief description of the Sub Agent's purpose and capabilities |
| `prompt` | string | Yes | Detailed behavior guidelines and system prompt for the Sub Agent |
| `model` | string | No | AI model identifier (e.g., "anthropic/claude-sonnet-4-20250514"). Choose a model that you prefer |
| `providerOptions` | object | No | Model-specific configuration options (temperature, maxOutputTokens, etc.) |
| `Data components` | object | No | Data components that the Sub Agent can use. See [Data Components](/visual-builder/structured-outputs/data-components) for details |
| `Artifact components` | array | No | Artifact components that the Sub Agent can use. See [Artifact Components](/visual-builder/structured-outputs/artifact-components) for details |
## Adding data components
Data components are used to render rich UI components directly in the chat. Before adding a data component, you will first need to create a data component. See the [Data Components](/visual-builder/structured-outputs/data-components) page for more information.
Then, add the data component to your Sub Agent by clicking the Sub Agent box and then selecting which data components you want to add.
## Adding artifact components
To create artifact components, see the [Artifact Components](/visual-builder/structured-outputs/artifact-components) page for details.
Add the artifact component to your Sub Agent by clicking on the Sub Agent box in the Agent, then selecting which artifact components you want to add.
When the Sub Agent uses tools or delegates to other Sub Agents, artifacts will be automatically created according to your defined schema, capturing the source and content of each interaction.
## Adding team agents
Team agents are agents that are part of the same project. You can add team agents to your Agent by dragging and dropping the **Team Agent** block from the top left onto the Canvas.
You can configure custom headers to send on every request to the team agent by clicking on the team agent box and then populating the **Headers** field with your custom headers.
## Adding external agents
External agents let you integrate agents built outside of Inkeep (using other frameworks or platforms) into your Agent.
You can add an external agent to your Agent by dragging and dropping the **External Agent** block from the top left onto the Canvas.
You can configure custom headers to send on every request to the external agent by clicking on the external agent box and then populating the **Headers** field with your custom headers.
# Manage API Authentication
URL: /api-reference/authentication/manage-api
Authentication modes for Manage API
***
title: Manage API Authentication
description: Authentication modes for Manage API
icon: "LuShield"
----------------
The Manage API (`agents-manage-api`) has two authentication modes:
### Secured Mode
When `INKEEP_AGENTS_MANAGE_API_BYPASS_SECRET` is set:
* Include the secret as a Bearer token in requests
* Recommended for production environments
### Open Mode
When `INKEEP_AGENTS_MANAGE_API_BYPASS_SECRET` is not set:
* No authentication required
* Useful for local development
# Run API Authentication
URL: /api-reference/authentication/run-api
Authentication modes for Run API
***
title: Run API Authentication
description: Authentication modes for Run API
icon: "LuShield"
----------------
The Run API (`agents-run-api`) has three authentication modes depending on your environment configuration:
### Development Mode
When `ENVIRONMENT=development`:
* No API key required
* Must include scope headers:
* `x-inkeep-tenant-id`
* `x-inkeep-project-id`
* `x-inkeep-agent-id`
```bash
curl -H "x-inkeep-tenant-id: tenant-123" \
-H "x-inkeep-project-id: project-456" \
-H "x-inkeep-agent-id: agent-789" \
https://localhost:3003/v1/chat/completions
```
### Standard Mode
When `ENVIRONMENT≠development` and `INKEEP_AGENTS_RUN_API_BYPASS_SECRET` is not set:
* Use API keys created from the Manage UI
* No additional headers required (scope encoded in key)
```bash
curl -H "Authorization: Bearer sk_live_abc123..." \
https://localhost:3003/v1/chat/completions
```
### Bypass Mode
When `ENVIRONMENT≠development` and `INKEEP_AGENTS_RUN_API_BYPASS_SECRET` is set:
**Option 1: Bypass Secret**
* Use the bypass secret as token
* Must include scope headers
```bash
curl -H "Authorization: Bearer YOUR_BYPASS_SECRET" \
-H "x-inkeep-tenant-id: tenant-123" \
-H "x-inkeep-project-id: project-456" \
-H "x-inkeep-agent-id: agent-789" \
https://run-api.example.com/chat/completions
```
**Option 2: Standard API Keys remain valid**
* Use API keys from the Manage UI
```bash
curl -H "Authorization: Bearer sk_live_xyz789..." \
https://run-api.example.com/chat/completions
```
## Running Multiple Instances
You can run multiple Run API instances with different auth configurations. If you're deploying Inkeep Agents to production, it is common to only expose the deployment of Run API in standard mode and all other services remain internal.
```bash
# Instance 1: Port 3003 with bypass secret (intended for internal purposes)
PORT=3003 INKEEP_AGENTS_RUN_API_BYPASS_SECRET=secret123 pnpm dev
# Instance 2: Port 3004 without bypass secret (intended for external purposes)
PORT=3004 pnpm dev
```
## Security Best Practices
1. **Production**: Always use Standard API keys
2. **Bypass Secret**: Use for internal services only
3. **API Keys**: Rotate regularly and set expiration dates
# Environment Configuration
URL: /community/contributing/environment-configuration
How to configure the environment variables for the Inkeep Agent Framework
***
title: Environment Configuration
description: How to configure the environment variables for the Inkeep Agent Framework
icon: "LuSettings"
------------------
# Environment Configuration
## Overview
The Inkeep Agents framework uses a **centralized environment configuration**. This approach provides a single source of truth for all environment variables across the monorepo, eliminating duplication and simplifying configuration management.
## Configuration Structure
### Single Root Configuration
All packages in the monorepo reference a **single `.env` file** at the repository root. This is different from the typical approach of having separate `.env` files per package.
```
agents-4/
├── .env # Main configuration (gitignored)
├── .env.example # Template with all variables
└── packages/
└── agents-core/
└── src/env.ts # Centralized env loader
```
### Loading Priority
Environment variables are loaded in the following order (highest priority first):
1. **`/package-name/.env`** Package specific configuration
2. **`.env`** - Main configuration file
3. **`~/.inkeep/config`** - User-global settings (shared across all repo copies)
4. **`.env.example`** - Default values
This hierarchy allows for flexible configuration management across different scenarios. If you have .env or .env.local in a package directory, they will override the root .env or .env.local for that package.
## Use Cases
### 1. Basic Local Development
For simple local development with a single repository copy:
```bash
# Copy the template
cp .env.example .env
# Edit .env with your configuration
vim .env
# Start development
pnpm dev
```
## Troubleshooting
### Environment variables not loading
1. Check loading order - later sources override earlier ones
2. Verify file paths are correct
3. Ensure `packages/agents-core` is built: `pnpm --filter @inkeep/agents-core build`
### Missing variables in production
Ensure all required variables are set in your deployment environment. The application will fail fast if critical variables are missing.
### Database connection issues
* For SQLite: Make sure youu are using an absolute path to the db file
# Contribute to Inkeep Open Source project
URL: /community/contributing/overview
How to contribute to the Inkeep Agent Framework
***
title: Contribute to Inkeep Open Source project
sidebarTitle: How to start
description: How to contribute to the Inkeep Agent Framework
icon: "LuZap"
-------------
# Making a Contribution
Thank you for your interest in contributing to the Agent Framework! This document provides guidelines and information for contributors.
# Launch the Visual Builder
### Prerequisites
Before getting started, ensure you have the following installed on your system:
* [Node.js](https://nodejs.org/en/download/) version 22 or higher
* [Docker](https://docs.docker.com/get-docker/)
* [pnpm](https://pnpm.io/installation) version 10 or higher
### Step 1: Clone the repository
```
git clone https://github.com/inkeep/agents.git
cd agents
```
### Step 2: Run the setup script
For first-time setup, run:
```bash
pnpm setup-dev
```
This will:
1. Create `.env` from the template
2. Set up user-global config at `~/.inkeep/config`
3. Install dependencies
4. Initialize the database, starting the postgres docker container and applying migrations
Add API keys for the AI providers you want to use to the root `.env`. You must have at least one AI provider configured.
```
ANTHROPIC_API_KEY=sk-ant-xyz789
OPENAI_API_KEY=sk-xxx
GOOGLE_GENERATIVE_AI_API_KEY=sk-xxx
```
Add your SigNoz API key to enable the traces feature (optional).
```
SIGNOZ_API_KEY=sk-xxx
```
Add your Nango secret key to enable the Nango credential store (optional).
```
NANGO_SECRET_KEY=sk-xxx
```
### Step 5: Run the agent framework
```bash
pnpm dev
```
### Step 6: Start building!
Open `http://localhost:3000` in the browser and start building agents.
# Push your project
A key advantage of the Inkeep agent framework is its seamless code-to-visual workflow: define your agents programmatically, push them to the Visual Builder, and continue developing with the intuitive drag-and-drop interface.
Follow the steps below to push your project using the [Inkeep CLI](/typescript-sdk/cli-reference).
### Step 1: Download the Inkeep CLI
```bash
pnpm install -g @inkeep/agents-cli
```
### Step 2: Push the project
```bash
cd agents-cookbook/template-projects/weather-project
inkeep push
```
The project will be pushed according to the project specified in the
`/agents-cookbook/template-projects/inkeep.config.ts` file, which is set to the `default` project by
default. Feel free to change it to your own project.
### Step 3: Observe the Agent in the Visual Builder
# Set up live traces
### Step 1: Launch docker containers
```bash
cd deploy/docker
docker compose up -d
```
### Step 2: Fetch SigNoz API Key
Open `http://localhost:3080` in the browser. Go to **Settings** → **Workspace Settings** → **API Keys** and copy the API key.
### Step 3: Configure environment variable
Create a `.env` file at `/agents-manage-ui/` with the following variable:
```
SIGNOZ_API_KEY=your-signoz-api-key-here
```
### Step 4: View your live traces
Refresh the live traces panel on the right to see your agents in action.
# Set up credentials
### Step 1: Create .env file and generate encryption key
```bash
cp deploy/docker/.env.nango.example deploy/docker/.env && encryption_key=$(openssl rand -base64 32) && sed -i '' "s|REPLACE_WITH_BASE64_256BIT_ENCRYPTION_KEY|$encryption_key|" deploy/docker/.env && echo "Docker environment file created with auto-generated encryption key"
```
### Step 2: Restart the containers
```bash
cd deploy/docker
docker compose up -d
```
### Step 3: Get your Nango API key
Open the Nango Dashboard: `http://localhost:3050` and navigate to **Environment Settings** → **API Keys** and copy the API key.
### Step 4: Configure environment variables
Navigate back to the root directory and paste the below command. Enter your Nango API key when prompted:
```bash
cd ../../
printf "Enter your Nango API key: " && read key && sed -i '' "s|^NANGO_SECRET_KEY=.*|NANGO_SECRET_KEY=$key|" agents-manage-api/.env agents-run-api/.env agents-manage-ui/.env && echo "Application files updated with Nango API key"
```
### Step 5: Start creating credentials!
Navigate to the Credentials tab in the left sidebar and click "Create credential".
# Development Workflow
### Git Hooks
This project uses Husky for Git hooks to maintain code quality. The hooks are automatically installed when you run `pnpm install`.
#### Pre-commit Hook
The pre-commit hook runs the following checks before allowing a commit:
1. **Type checking** - Ensures type safety across all packages
2. **Tests** - Runs the test suite
##### Bypassing Checks
While we recommend running all checks, there are legitimate cases where you might need to bypass them:
**Skip typecheck only (tests still run):**
```bash
SKIP_TYPECHECK=1 git commit -m "WIP: debugging issue"
```
**Skip all hooks (use sparingly):**
```bash
git commit --no-verify -m "emergency: hotfix for production"
```
> **Note:** Use these bypass mechanisms sparingly. They're intended for:
>
> * Work-in-progress commits that you'll fix before pushing
> * Emergency fixes where speed is critical
> * Commits that only touch non-code files (though hooks are smart enough to handle this)
### Code Quality
#### Type Checking
Run type checking across all packages:
```bash
pnpm typecheck
```
#### Linting
Run the linter:
```bash
pnpm lint
```
Format code automatically:
```bash
pnpm format
```
#### Testing
Run tests:
```bash
pnpm test # Run all tests
pnpm test:watch # Run tests in watch mode
pnpm test:coverage # Run tests with coverage report
```
### Building
Build all packages:
```bash
pnpm build
```
# CLI Development
## Running the CLI Locally
When developing the CLI, you can run the local version directly without global installation:
```bash
# Build the CLI first
cd agents-cli
pnpm build
# Run the local CLI from the repository root
node agents-cli/dist/index.js --version
# Or use the convenience script (if available)
./scripts/inkeep-local.sh --version
```
## Testing CLI Changes
1. **Build the CLI after making changes:**
```bash
cd agents-cli
pnpm build
```
2. **Test commands locally:**
```bash
# From repository root
node agents-cli/dist/index.js push examples/agent-configurations
node agents-cli/dist/index.js chat
```
3. **Run CLI tests:**
```bash
cd agents-cli
pnpm test
```
## Switching Between Local and Published CLI
During development, you may need to test both the local development version and the published npm package:
```bash
# Use local development version
node /path/to/agents/agents-cli/dist/index.js --version
# Use globally installed published version
inkeep --version
```
For detailed information about switching between versions, see the `INKEEP_CLI_SWITCHING.md` file in the repository root.
# Commit Messages
We follow conventional commit format:
```
type(scope): description
[optional body]
[optional footer]
```
Types:
* `feat`: New feature
* `fix`: Bug fix
* `docs`: Documentation changes
* `style`: Code style changes (formatting, etc.)
* `refactor`: Code refactoring
* `test`: Test changes
* `chore`: Build process or auxiliary tool changes
# Pull Requests
1. Fork the repository
2. Create a feature branch (`git checkout -b feat/amazing-feature`)
3. Make your changes
4. Ensure all checks pass (`pnpm typecheck && pnpm test`)
5. Commit your changes (following commit message guidelines)
6. Push to your fork
7. Open a pull request
### PR Guidelines
* Keep PRs focused on a single feature or fix
* Update tests for any behavior changes
* Update documentation as needed
* Ensure CI passes before requesting review
# Continuous Integration
Our CI pipeline runs on all pull requests and includes:
* Type checking (`pnpm typecheck`)
* Tests (`pnpm test`)
* Build verification (`pnpm build`)
These checks must pass before a PR can be merged. The same checks run in pre-commit hooks to catch issues early.
# Questions?
If you have questions about contributing, please:
1. Check existing issues and discussions
2. Open a new issue if your question isn't addressed
3. Reach out to the maintainers
Thank you for contributing!
# Data Layer constraints on Project relationships
URL: /community/contributing/project-constraints
How the Inkeep Agent Framework ensures data integrity with project constraints
***
title: Data Layer constraints on Project relationships
sidebarTitle: Project Data Layer
description: How the Inkeep Agent Framework ensures data integrity with project constraints
icon: "LuTriangleAlert"
-----------------------
# Project Constraints and Validation
The Inkeep Agent Framework implements multiple layers of validation to ensure that all agents and resources are associated with valid projects.
## Database-Level Constraints
### Foreign Key Constraints
All tables that reference projects include foreign key constraints to ensure referential integrity:
```sql
FOREIGN KEY (tenant_id, project_id)
REFERENCES projects(tenant_id, id)
ON DELETE CASCADE
```
This ensures that:
* No data can be inserted for non-existent projects
* Deleting a project cascades to remove all associated resources
* Data integrity is maintained at the database level
### Tables with Project Constraints
The following tables have foreign key constraints to the `projects` table:
1. `agent` - Agent definitions (top-level Agents)
2. `sub_agents` - Sub Agent configurations
3. `sub_agent_relations` - Relationships between Sub Agents
4. `tools` - Tool configurations
5. `context_configs` - Context configurations
6. `external_agents` - External agent references
7. `conversations` - Chat conversations
8. `messages` - Chat messages
9. `tasks` - Task records
10. And more...
## Runtime Validation
### CLI Validation
The Inkeep CLI validates project existence before pushing agents:
```typescript
// CLI checks if project exists
const existingProject = await getProject(dbClient)({
scopes: { tenantId, projectId },
});
if (!existingProject) {
// Prompt user to create project
// ...
}
```
### Data Access Layer Validation
The core package provides validation utilities for runtime checks:
```typescript
import { validateProjectExists } from "@inkeep/agents-core";
// Validate before any operation
await validateProjectExists(db, tenantId, projectId);
```
### Wrapped Operations
Data access functions can be wrapped with automatic validation:
```typescript
import { withProjectValidation } from "@inkeep/agents-core";
const validatedCreateAgent = withProjectValidation(db, createAgent);
// Now automatically validates project before creating agent
```
## Implementation Details
### Schema Definition
```typescript
export const agents = sqliteTable(
"agent",
{
tenantId: text("tenant_id").notNull(),
projectId: text("project_id").notNull(),
// ... other columns
},
(table) => [
primaryKey({ columns: [table.tenantId, table.projectId, table.id] }),
foreignKey({
columns: [table.tenantId, table.projectId],
foreignColumns: [projects.tenantId, projects.id],
name: "agent_project_fk",
}),
]
);
```
### Enabling Foreign Keys in SQLite
SQLite requires explicit enabling of foreign key constraints:
```sql
PRAGMA foreign_keys = ON;
```
This should be set when creating the database connection:
```typescript
const client = createClient({
url: dbUrl,
authToken: authToken,
});
// Enable foreign keys
await client.execute("PRAGMA foreign_keys = ON");
```
## Error Handling
When a constraint violation occurs, appropriate error messages guide users:
### CLI Error
```
⚠ Project "my-project" does not exist
? Would you like to create it? (Y/n)
```
### Database Error
```
Error: Project with ID "my-project" does not exist for tenant "my-tenant".
Please create the project first before adding resources to it.
```
## Best Practices
1. **Always validate at multiple levels**: Database constraints, runtime validation, and UI validation
2. **Provide clear error messages**: Help users understand what went wrong and how to fix it
3. **Offer solutions**: When a project doesn't exist, offer to create it
4. **Use transactions**: Ensure atomicity when creating projects and related resources
5. **Test constraints**: Verify that constraints work as expected in tests
## Migration Guide
For existing databases without constraints:
1. **Backup your database** before applying migrations
2. **Check for orphaned data**: Find resources referencing non-existent projects
3. **Clean up orphaned data** or create missing projects
4. **Apply foreign key constraints** using migrations
5. **Enable foreign key enforcement** in your database connection
```sql
-- Find orphaned agents
SELECT a.* FROM agent a
LEFT JOIN projects p
ON a.tenant_id = p.tenant_id
AND a.project_id = p.id
WHERE p.id IS NULL;
```
## Benefits
* **Data Integrity**: Prevents orphaned data and maintains consistency
* **Clear User Experience**: Users are guided to create projects when needed
* **Easier Debugging**: Constraint violations are caught early
* **Simplified Cleanup**: Cascading deletes remove all related data
* **Better Documentation**: Constraints document relationships in the schema
# Spans and Traces
URL: /community/contributing/spans
OpenTelemetry spans for distributed tracing and observability in the Inkeep Agent Framework
***
title: Spans and Traces
description: OpenTelemetry spans for distributed tracing and observability in the Inkeep Agent Framework
icon: "LuBug"
-------------
## Overview
The Inkeep Agent Framework uses OpenTelemetry for distributed tracing and observability. Spans provide detailed visibility into the execution flow of agents, context resolution, tool execution, and other framework operations.
## Getting Started with Spans
### 1. Import Required Dependencies
```typescript
import { SpanStatusCode, type Span } from "@opentelemetry/api";
import { getTracer, setSpanWithError } from "../tracer";
```
### 2. Get the Tracer
```typescript
// Use the centralized tracer utility
const tracer = getTracer("your-service-name");
```
## Creating and Using Spans
```typescript
return tracer.startActiveSpan(
"context.resolve",
{
attributes: {
"context.config_id": contextConfig.id,
"context.trigger_event": options.triggerEvent,
},
},
async (span: Span) => {
try {
// Your operation logic here
return result;
} catch (error) {
// Use setSpanWithError for consistent error handling
setSpanWithError(span, error);
throw error;
}
}
);
```
## Setting Span Attributes
### Basic Attributes
```typescript
span.setAttributes({
"user.id": userId,
"request.method": "POST",
});
```
## Adding Events to Spans
### Recording Important Milestones
```typescript
// Add events for significant operations
span.addEvent("context.fetch_started", {
definitionId: definition.id,
url: definition.fetchConfig.url,
});
```
### Error Events
```typescript
span.addEvent("error.validation_failed", {
definitionId: definition.id,
error_type: "json_schema_validation",
error_details: errorMessage,
});
```
## Error Handling and Status
### Using setSpanWithError Utility
The framework provides a convenient `setSpanWithError` utility function that handles error recording and status setting:
```typescript
try {
// Your operation
} catch (error) {
// Use the setSpanWithError utility for consistent error handling
setSpanWithError(span, error);
throw error;
}
```
## Best Practices
### 1. Consistent Naming Convention
The span naming convention follows a hierarchical structure that mirrors your code organization.
```typescript
// Format: 'class.function'
// Use descriptive span names that follow a hierarchical structure
// Agent operations
"agent.generate";
"agent.tool_execute";
"agent.transfer";
// Context operations
"context.resolve";
"context.fetch";
```
#### Naming Rules
1. **Class First**: Start with the class/module name (e.g., `agent`, `context`, `tool`)
2. **Function Second**: Follow with the specific function/method (e.g., `generate`, `resolve`)
3. **Use Underscores**: For multi-word functions, use underscores (e.g., `tool_execute`, `cache_lookup`)
4. **Consistent Casing**: Use lowercase with underscores for consistency
## Configuration and Setup
### Environment Variables
```bash
# OpenTelemetry configuration
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:4317
```
### Instrumentation Setup
The framework automatically sets up OpenTelemetry instrumentation in `src/instrumentation.ts`:
## Examples in the Codebase
### Agent Operations
See `src/agents/Agent.ts` for span usage in agent generation and tool execution.
**Example from Agent.ts:**
```typescript
// Class: Agent
// Function: generate
return tracer.startActiveSpan(
"agent.generate",
{
attributes: {
"agent.id": this.id,
"agent.name": this.name,
},
},
async (span: Span) => {
// ... implementation
}
);
```
## Summary
Spans provide powerful observability into your Inkeep Agent Framework operations. By following these patterns:
1. **Use `getTracer()`** for consistent tracing
2. **Use consistent naming**
3. **Set meaningful attributes** for searchability
4. **Handle errors properly** using `setSpanWithError` for consistent error handling
5. **Use `startActiveSpan`** for automatic lifecycle management
This will give you comprehensive visibility into your agent operations, making debugging and performance optimization much easier.
# Datadog
URL: /self-hosting/add-other-services/datadog-apm
Add Datadog APM to your Inkeep Agent Framework services
***
title: Datadog
sidebarTitle: Add Datadog
description: Add Datadog APM to your Inkeep Agent Framework services
keywords: Datadog, monitoring, distributed tracing
icon: "brand/DatadogIcon"
-------------------------
## Overview
Learn how to add Datadog APM to your Inkeep Agent Framework services.
## Step 1: Install Datadog APM
From the root of your workspace, run the following command:
```bash
pnpm install dd-trace
```
## Step 2: Set up tracer.ts
In `apps/run-api` and `apps/manage-api` create a new file called `tracer.ts` and add the following code:
```typescript
import tracer from "dd-trace";
tracer.init(); // initialized in a different file to avoid hoisting.
export default tracer;
```
In `apps/run-api/src/index.ts` and `apps/manage-api/src/index.ts` add the following code to the top of the file before all other imports:
```typescript
import "./tracer";
```
## Additional Resources
For more information on how to configure APM, you can consult the official Datadog Node.js [documentation](https://app.datadoghq.com/apm/service-setup?architecture=host-based\&framework=typescript\&language=node\&product=apm).
# Sentry
URL: /self-hosting/add-other-services/sentry
Add Sentry monitoring to your agent services
***
title: Sentry
sidebarTitle: Add Sentry
description: Add Sentry monitoring to your agent services
keywords: Sentry, error tracking, monitoring, distributed tracing
icon: "brand/SentryIcon"
------------------------
## Overview
Learn how to add Sentry monitoring to your Inkeep Agent Framework services.
## Step 1: Install Sentry
```bash
pnpm install @sentry/node
```
## Step 2: Update your `.env` file
Add your Sentry DSN to the `.env` file in the root of your workspace.
```bash
SENTRY_DSN=https://@sentry.io/
```
## Step 3: Configure Sentry
In `apps/run-api` and `apps/manage-api` create a new file called `sentry.ts` and add the following code:
```typescript
import * as Sentry from "@sentry/node";
Sentry.init({
dsn: process.env.SENTRY_DSN,
sampleRate: 1.0,
tracesSampleRate: 1.0,
});
```
In `apps/run-api/src/index.ts` and `apps/manage-api/src/index.ts` add the following code to the top of the file before all other imports:
```typescript
import "./sentry";
```
## Forward Error Logs to Sentry
You can use [pino-sentry-transport](https://github.com/tomer-yechiel/pino-sentry-transport) to forward error logs to Sentry.
### Step 1: Install pino-sentry-transport
```bash
pnpm install pino-sentry-transport
```
### Step 2: Configure pino-sentry-transport
Add the following code to the top of your `apps/run-api/src/index.ts` file:
```typescript
logger = getLogger('agents-run-api');
logger.addTransport({
target: 'pino-sentry-transport',
options: {
sentry: {
dsn: process.env.SENTRY_DSN,
},
},
});
```
Add the following code to the top of your `apps/manage-api/src/index.ts` file:
```typescript
logger = getLogger('agents-manage-api');
logger.addTransport({
target: 'pino-sentry-transport',
options: {
sentry: {
dsn: process.env.SENTRY_DSN,
},
},
});
```
## Additional Resources
For more information on how to configure Sentry, you can consult the official Sentry Node.js [documentation](https://docs.sentry.io/platforms/node/).
# Chat Button
URL: /talk-to-your-agents/javascript/chat-button
Learn how to use the chat button component in JavaScript
***
title: Chat Button
description: Learn how to use the chat button component in JavaScript
icon: "LuMessageCircle"
-----------------------
The chat button component is a simple way to trigger the Inkeep chat bubble in your JavaScript application.
## Quick Start
Add the below `
```
Insert the Chat Button by using the `Inkeep.ChatButton()` function.
```ts
const config: InkeepChatButtonProps = {
aiChatSettings: {
agentUrl: "https://your-api.example.com/api/chat",
apiKey: process.env.INKEEP_API_KEY, // Your API key
},
};
const chatButton = Inkeep.ChatButton(config);
```
## Config
### Base Settings
### Open Settings
### AI Chat Settings
# Custom Trigger
URL: /talk-to-your-agents/javascript/custom-trigger
Create custom UI elements to trigger Inkeep modals with complete control over appearance and behavior in JavaScript.
***
title: Custom Trigger
description: Create custom UI elements to trigger Inkeep modals with complete control over appearance and behavior in JavaScript.
icon: "LuMousePointerClick"
---------------------------
## Overview
Custom triggers give you complete control over how users open Inkeep modals in your JavaScript application. Instead of using pre-built widgets like `Inkeep.ChatButton()`, you can create your own UI elements that match your design system while maintaining full functionality.
## Quick Start
Add the below `
```
Insert the ModalChat widget by using the `Inkeep.ModalChat()` function.
```js
const config = {
baseSettings: {
apiKey: "YOUR_API_KEY",
},
aiChatSettings: {
aiAssistantName: "Keepie",
},
openSettings: {
onOpenChange: handleOpenChange,
},
};
// Initialize modal chat
const modalChat = Inkeep.ModalChat(config);
function handleOpenChange(newOpen) {
modalChat.update({ openSettings: { isOpen: newOpen } });
}
// trigger
document.querySelector("#chat-button").addEventListener("click", () => {
modalChat.update({ openSettings: { isOpen: true } });
});
// Access chat methods
modalChat.clearChat();
```
## Config
### Base Settings
### AI Chat Settings
### Open Settings
# Embedded Chat
URL: /talk-to-your-agents/javascript/embedded-chat
Integrate Inkeep's embedded chat component directly into your React application for inline agent conversations.
***
title: Embedded Chat
description: Integrate Inkeep's embedded chat component directly into your React application for inline agent conversations.
icon: "LuMonitor"
-----------------
The EmbeddedChat widget provides a fully embedded chat interface that you can integrate directly into your JavaScript application's layout. Unlike modal or sidebar implementations, the embedded chat becomes part of your page structure, perfect for dedicated support pages, dashboards, or help centers.
## Quick Start
Add the below `
```
Define an element in your page that will be the "container" for the embedded chat.
```html
```
Insert the EmbeddedChat widget by using the `Inkeep.EmbeddedChat()` function.
```ts
```
## Config
### Base Settings
### AI Chat Settings
# Add Sidebar Chat to React
URL: /talk-to-your-agents/javascript/side-bar-chat
Integrate Inkeep's sidebar chat component into your React application for seamless agent conversations.
***
title: Add Sidebar Chat to React
sidebarTitle: Sidebar Chat
description: Integrate Inkeep's sidebar chat component into your React application for seamless agent conversations.
icon: "LuPanelLeft"
-------------------
The SidebarChat widget provides a slide-out panel interface for conversing with your agents. It can be positioned on either side of your application and supports both manual triggering and automatic element triggers.
## Quick Start
Add the below `
```
Define an element in your page that will be the "container" for the embedded chat.
```html
```
Add a button element that will trigger the sidebar chat and give it the data attribute data-inkeep-sidebar-chat-trigger. You can also use your own custom attribute if you prefer, just be sure to pass it to the triggerSelector prop.
```html
```
Insert the EmbeddedChat widget by using the `Inkeep.EmbeddedChat()` function.
```ts
```
## Config
### Base Settings
### AI Chat Settings
### Open Settings
# Chat Button
URL: /talk-to-your-agents/react/chat-button
Learn how to use the chat button component in React
***
title: Chat Button
description: Learn how to use the chat button component in React
icon: "LuMessageCircle"
-----------------------
The chat button component is a simple way to trigger the Inkeep chat bubble.
## Installation
```bash title="npm"
npm install @inkeep/agents-ui
```
```bash title="yarn"
yarn add @inkeep/agents-ui
```
```bash title="pnpm"
pnpm add @inkeep/agents-ui
```
## Quick Start
Use an API key for secure authentication in production:
```tsx
import { InkeepChatButton, type InkeepChatButtonProps } from "@inkeep/agents-ui";
const buttonProps: InkeepChatButtonProps = {
aiChatSettings: {
agentUrl: "https://your-api.example.com/api/chat",
apiKey: process.env.REACT_APP_INKEEP_API_KEY, // Your API key
},
};
const ChatButton = () => {
return ;
};
```
**To get an API key:**
1. Open the Visual Builder Dashboard
2. Navigate to your Project → **API Keys**
3. Click **Create New Key** and select your agent
4. Copy the key (shown once) and store it in your environment variables
For local development, use headers with your agent IDs:
```tsx
import {
InkeepChatButton,
type InkeepChatButtonProps,
} from "@inkeep/agents-ui";
const buttonProps: InkeepChatButtonProps = {
aiChatSettings: {
agentUrl: "http://localhost:3003/api/chat",
headers: {
"x-inkeep-tenant-id": "your-tenant-id",
"x-inkeep-project-id": "your-project-id",
"x-inkeep-agent-id": "your-agent-id",
},
},
};
const ChatButton = () => {
return ;
};
```
**Note:** Run your API server with `ENVIRONMENT=development` to bypass authentication.
## Props
### Base Settings
### Open Settings
### AI Chat Settings
# Custom Trigger
URL: /talk-to-your-agents/react/custom-trigger
Create custom UI elements to trigger Inkeep modals with complete control over appearance and behavior.
***
title: Custom Trigger
description: Create custom UI elements to trigger Inkeep modals with complete control over appearance and behavior.
icon: "LuMousePointerClick"
---------------------------
## Overview
Custom triggers give you complete control over how users open Inkeep modals in your React application. Instead of using pre-built components like `InkeepChatButton`, you can create your own UI elements that match your design system while maintaining full functionality.
## Installation
```bash title="npm"
npm install @inkeep/agents-ui
```
```bash title="yarn"
yarn add @inkeep/agents-ui
```
```bash title="pnpm"
pnpm add @inkeep/agents-ui
```
## Quick Start
Use an API key for secure authentication in production:
```tsx
import { useState } from "react";
import { InkeepModalChat, type InkeepModalChatProps } from "@inkeep/agents-ui";
function App() {
const [isModalOpen, setIsModalOpen] = useState(false);
const modalProps: InkeepModalChatProps = {
aiChatSettings: {
agentUrl: "https://your-api.example.com/api/chat",
apiKey: process.env.REACT_APP_INKEEP_API_KEY, // Your API key
},
openSettings: {
isOpen: isModalOpen,
onOpenChange: setIsModalOpen,
},
};
return (
<>
>
);
}
```
**To get an API key:**
1. Open the Visual Builder Dashboard
2. Navigate to your Project → **API Keys**
3. Click **Create New Key** and select your agent
4. Copy the key (shown once) and store it in your environment variables
For local development, use headers with your agent IDs:
```tsx
import { useState } from "react";
import {
InkeepModalChat,
type InkeepModalChatProps,
} from "@inkeep/cxkit-react";
function App() {
const [isModalOpen, setIsModalOpen] = useState(false);
const modalProps: InkeepModalChatProps = {
aiChatSettings: {
agentUrl: "http://localhost:3003/api/chat",
headers: {
"x-inkeep-tenant-id": "your-tenant-id",
"x-inkeep-project-id": "your-project-id",
"x-inkeep-agent-id": "your-agent-id",
},
},
openSettings: {
isOpen: isModalOpen,
onOpenChange: setIsModalOpen,
},
};
return (
<>
>
);
}
```
**Note:** Run your API server with `ENVIRONMENT=development` to bypass authentication.
## Props
### Base Settings
### AI Chat Settings
### Open Settings
# Embedded Chat
URL: /talk-to-your-agents/react/embedded-chat
Integrate Inkeep's embedded chat component directly into your React application for inline agent conversations.
***
title: Embedded Chat
description: Integrate Inkeep's embedded chat component directly into your React application for inline agent conversations.
icon: "LuMonitor"
-----------------
The InkeepEmbeddedChat component provides a fully embedded chat interface that you can integrate directly into your React application's layout. Unlike modal or sidebar implementations, the embedded chat becomes part of your page structure, perfect for dedicated support pages, dashboards, or help centers.
## Installation
```bash title="npm"
npm install @inkeep/agents-ui
```
```bash title="yarn"
yarn add @inkeep/agents-ui
```
```bash title="pnpm"
pnpm add @inkeep/agents-ui
```
## Quick Start
Use an API key for secure authentication in production:
```tsx
import { InkeepEmbeddedChat, type InkeepEmbeddedChatProps } from "@inkeep/agents-ui";
export default function App() {
const embeddedChatProps: InkeepEmbeddedChatProps = {
aiChatSettings: {
agentUrl: "https://your-api.example.com/api/chat",
apiKey: process.env.REACT_APP_INKEEP_API_KEY, // Your API key
},
};
return ;
}
```
**To get an API key:**
1. Open the Visual Builder Dashboard
2. Navigate to your Project → **API Keys**
3. Click **Create New Key** and select your agent
4. Copy the key (shown once) and store it in your environment variables
For local development, use headers with your agent IDs:
```tsx
import {
InkeepEmbeddedChat,
type InkeepEmbeddedChatProps,
} from "@inkeep/agents-ui";
export default function App() {
const embeddedChatProps: InkeepEmbeddedChatProps = {
aiChatSettings: {
agentUrl: "http://localhost:3003/api/chat",
headers: {
"x-inkeep-tenant-id": "your-tenant-id",
"x-inkeep-project-id": "your-project-id",
"x-inkeep-agent-id": "your-agent-id",
},
},
};
return ;
}
```
**Note:** Run your API server with `ENVIRONMENT=development` to bypass authentication.
## Props
### Base Settings
### AI Chat Settings
# Add Sidebar Chat to React
URL: /talk-to-your-agents/react/side-bar-chat
Integrate Inkeep's sidebar chat component into your React application for seamless agent conversations.
***
title: Add Sidebar Chat to React
sidebarTitle: Sidebar Chat
description: Integrate Inkeep's sidebar chat component into your React application for seamless agent conversations.
icon: "LuPanelLeft"
-------------------
The InkeepSidebarChat component provides a slide-out panel interface for conversing with your agents. It can be positioned on either side of your application and supports both manual triggering and automatic element triggers.
## Installation
```bash title="npm"
npm install @inkeep/agents-ui
```
```bash title="yarn"
yarn add @inkeep/agents-ui
```
```bash title="pnpm"
pnpm add @inkeep/agents-ui
```
## Quick Start
Use an API key for secure authentication in production:
### Trigger through React state
```tsx
import { useState } from "react";
import { InkeepSidebarChat, type InkeepSidebarChatProps } from "@inkeep/agents-ui";
export default function App() {
const [isOpen, setIsOpen] = useState(false);
const sidebarChatProps: InkeepSidebarChatProps = {
aiChatSettings: {
agentUrl: "https://your-api.example.com/api/chat",
apiKey: process.env.REACT_APP_INKEEP_API_KEY, // Your API key
},
position: "right",
openSettings: {
isOpen: isOpen,
onOpenChange: setIsOpen,
},
};
return (
);
}
```
### Trigger through data attributes
```tsx
import {
InkeepSidebarChat,
type InkeepSidebarChatProps,
} from "@inkeep/agents-ui";
export default function App() {
const sidebarChatProps: InkeepSidebarChatProps = {
aiChatSettings: {
agentUrl: "https://your-api.example.com/api/chat",
apiKey: process.env.REACT_APP_INKEEP_API_KEY, // Your API key
},
position: "right",
};
return (
);
}
```
**To get an API key:**
1. Open the Visual Builder Dashboard
2. Navigate to your Project → **API Keys**
3. Click **Create New Key** and select your agent
4. Copy the key (shown once) and store it in your environment variables
For local development, use headers with your agent IDs:
### Trigger through React state
```tsx
import { useState } from "react";
import {
InkeepSidebarChat,
type InkeepSidebarChatProps,
} from "@inkeep/agents-ui";
export default function App() {
const [isOpen, setIsOpen] = useState(false);
const sidebarChatProps: InkeepSidebarChatProps = {
aiChatSettings: {
agentUrl: "http://localhost:3003/api/chat",
headers: {
"x-inkeep-tenant-id": "your-tenant-id",
"x-inkeep-project-id": "your-project-id",
"x-inkeep-agent-id": "your-agent-id",
},
},
position: "right",
openSettings: {
isOpen: isOpen,
onOpenChange: setIsOpen,
},
};
return (
);
}
```
### Trigger through data attributes
```tsx
import {
InkeepSidebarChat,
type InkeepSidebarChatProps,
} from "@inkeep/agents-ui";
export default function App() {
const sidebarChatProps: InkeepSidebarChatProps = {
aiChatSettings: {
agentUrl: "http://localhost:3003/api/chat",
headers: {
"x-inkeep-tenant-id": "your-tenant-id",
"x-inkeep-project-id": "your-project-id",
"x-inkeep-agent-id": "your-agent-id",
},
},
position: "right",
};
return (
);
}
```
**Note:** Run your API server with `ENVIRONMENT=development` to bypass authentication.
## Configuration Options
### Required Props
| Property | Type | Description |
| ------------------------- | ------ | --------------------------------------------------- |
| `aiChatSettings` | object | Configuration for the AI chat connection |
| `aiChatSettings.agentUrl` | string | The URL of your agent endpoint |
| `aiChatSettings.headers` | object | Headers for authentication and agent identification |
## Props
### Base Settings
### AI Chat Settings
### Open Settings
# Build chat UIs with Vercel AI Elements
URL: /talk-to-your-agents/vercel-ai-sdk/ai-elements
Use Vercel AI Elements to quickly assemble production-ready chat interfaces that connect to your Inkeep agent.
***
title: Build chat UIs with Vercel AI Elements
sidebarTitle: AI Elements
description: Use Vercel AI Elements to quickly assemble production-ready chat interfaces that connect to your Inkeep agent.
icon: LuPackage
keywords: Vercel AI Elements, shadcn ui, chat components, React, agents
-----------------------------------------------------------------------
## Overview
[Vercel AI Elements](https://ai-sdk.dev/elements/overview) is a set of prebuilt, headless-first UI primitives for building AI chat interfaces. Think of it as a `shadcn/ui`-like library of UI components for conversational experiences.
The library works out of the box with Inkeep Agents via the `/chat` [API endpoint](/talk-to-your-agents/api) since it follows the streaming protocol used by AI Elements.
For fully custom `useChat` hooks and lower-level control, see the [useChat guide](/talk-to-your-agents/vercel-ai-sdk/use-chat).
## Using AI Elements
```tsx
import { Conversation, Message, PromptInput, Actions } from '@ai-sdk/react-elements';
import { useChat } from '@ai-sdk/react';
export default function ChatWithElements() {
const { messages, sendMessage } = useChat({
transport: new DefaultChatTransport({
api: "${process.env.NEXT_PUBLIC_INKEEP_AGENTS_RUN_API_URL}/api/chat", //
headers: {
"x-inkeep-tenant-id": "default",
"x-inkeep-project-id": "weather-project",
"x-inkeep-agent-id": "weather-agent",
},
})
});
return (
{messages.map(message => (
))}
);
}
```
## Install (one-liner)
```sh
npx ai-elements@latest
```
This CLI adds selected components to your project under `@/components/ai-elements/` and wires up any required shadcn/ui primitives.
## Component quick reference
* **Core chat**: `Conversation`, `Message`, `PromptInput`, `Response`, `Actions`, `Sources`
* **Reasoning & tools**: `Reasoning`, `Tool`, `Task`, `InlineCitation`, `Context`
* **Workflow (React Flow)**: `Canvas`, `Node`, `Edge`, `Connection`, `Controls`, `Panel`, `Toolbar`
* **Coding artifacts**: `CodeBlock`, `Artifact`, `WebPreview`, `Image`
* **UX extras**: `Suggestion`, `Branch`, `Loader`, `OpenIn`
See the [AI Elements](https://ai-sdk.dev/elements/overview) site for detailed props and examples.
# Use Inkeep agents with Vercel AI SDK
URL: /talk-to-your-agents/vercel-ai-sdk/inkeep-provider
A custom AI SDK provider that lets you use Inkeep agents with generateText, streamText, and other AI SDK functions.
***
title: Use Inkeep agents with Vercel AI SDK
sidebarTitle: Inkeep Provider
description: A custom AI SDK provider that lets you use Inkeep agents with generateText, streamText, and other AI SDK functions.
icon: LuZap
keywords: Vercel AI SDK, provider, generateText, streamText, tool calling, agents
---------------------------------------------------------------------------------
## Overview
The `@inkeep/ai-sdk-provider` package is a custom AI SDK provider that exposes Inkeep agents through the Vercel AI SDK. This lets you call your agents with `generateText()` and `streamText()`.
## Installation
```bash
npm install @inkeep/ai-sdk-provider ai
```
## Basic Usage
### Text Generation
```typescript
import { generateText } from 'ai';
import { createInkeep } from '@inkeep/ai-sdk-provider';
const inkeep = createInkeep({
baseURL: process.env.INKEEP_AGENTS_RUN_API_URL, // Required
apiKey: '', // Created in the Agents Dashboard
headers: { // Optional if you are developing locally and don't want to use an api key
'x-inkeep-agent-id': 'your-agent-id',
'x-inkeep-tenant-id': 'your-tenant-id',
'x-inkeep-project-id': 'your-project-id',
},
});
const { text } = await generateText({
model: inkeep(),
prompt: 'What is the weather in NYC?',
});
console.log(text);
```
### Streaming Responses
```typescript
import { streamText } from 'ai';
import { createInkeep } from '@inkeep/ai-sdk-provider';
const inkeep = createInkeep({
baseURL: process.env.INKEEP_AGENTS_RUN_API_URL,
apiKey: '', // The agent ID is encoded in the API key
headers: {
'x-emit-operations': 'true', // Enable tool event streaming
},
});
const result = await streamText({
model: inkeep(),
prompt: 'Plan an event in NYC',
});
for await (const chunk of result.textStream) {
process.stdout.write(chunk);
}
```
## Configuration
### Provider Settings
```typescript
createInkeep({
baseURL: string, // Required. Your agents-run-api URL
apiKey?: string, // Optional. Bearer token for authentication
headers?: Record, // Optional. Additional headers
})
```
### Provider Options
Pass options when creating a provider instance:
```typescript
const provider = inkeep({
conversationId: 'conv-456',
headers: { 'user-id': 'user-789' },
});
```
## Tool Call Observability
To receive tool call and result events in your stream, include the `x-emit-operations` header:
```typescript
const inkeep = createInkeep({
baseURL: process.env.INKEEP_AGENTS_RUN_API_URL,
apiKey: '', // The agent ID is encoded in the API key
headers: {
'x-emit-operations': 'true',
},
});
const result = await streamText({
model: inkeep(),
prompt: 'Search for recent papers on AI',
});
for await (const event of result.fullStream) {
switch (event.type) {
case 'tool-call':
console.log(`Calling: ${event.toolName}`);
break;
case 'tool-result':
console.log(`Result: ${event.toolName}`);
break;
}
}
```
### Supported Stream Events
**Text events** (always emitted):
* `text-start`, `text-delta`, `text-end`
**Tool events** (requires `x-emit-operations: true`):
* `tool-call` - Tool invocations (including agent transfers and delegations)
* `tool-result` - Tool results (including delegation returns)
**Control events** (always emitted):
* `finish` - Stream completion with usage stats
* `error` - Stream errors
## Next Steps
Build React chat interfaces with streaming responses.
Use prebuilt UI components for chat experiences.
Learn about the underlying HTTP API endpoint.
# Create custom UIs using the Vercel AI SDK
URL: /talk-to-your-agents/vercel-ai-sdk/use-chat
Use the Vercel AI SDK's useChat hook to build React chat interfaces that stream responses from your agent.
***
title: Create custom UIs using the Vercel AI SDK
sidebarTitle: useChat hook
description: Use the Vercel AI SDK's useChat hook to build React chat interfaces that stream responses from your agent.
icon: LuCode
keywords: Vercel AI SDK, useChat, React, streaming, chat interface, agents
--------------------------------------------------------------------------
## Overview
Agents built with Inkeep have an `/api/chat` [API endpoint](/talk-to-your-agents/chat-api) that is compatible with Vercel AI SDK's streaming protocol, so it works out of the box with Vercel's AI SDK ecosystem.
To build totally custom UIs, you have two options in the AI SDK ecosystem:
* Use `useChat` hook to build custom UIs in React, Svelte, Vue.js, and Angular. (**← this guide**)
* Use the [AI Elements](/talk-to-your-agents/vercel-ai-sdk/ai-elements) library for a shadcn-like chat primitives.
## Using `useChat`
Install the Vercel AI SDK in your React application:
```bash
npm install ai @ai-sdk/react
```
## Basic Configuration
Here's a minimal example of using `useChat` with your agent:
```tsx
"use client";
import { useChat } from "@ai-sdk/react";
import { DefaultChatTransport } from "ai";
import { useState } from "react";
export default function Page() {
const { messages, sendMessage } = useChat({
transport: new DefaultChatTransport({
api: "${process.env.NEXT_PUBLIC_INKEEP_AGENTS_RUN_API_URL}/api/chat", //
headers: {
"x-inkeep-tenant-id": "default",
"x-inkeep-project-id": "activities-planner",
"x-inkeep-agent-id": "activities-planner",
},
}),
});
const [input, setInput] = useState("");
return (
);
}
```
## Configuration Options
### API Endpoint
The `api` parameter should point to your Run API's chat endpoint:
* **Local development**: `http://localhost:3003/api/chat`
* **Production**: `https://your-run-api-domain.com/api/chat`
<>
## Authentication
Choose the authentication method:
**Create an API Key:**
1. Open the Visual Builder Dashboard
2. Go to your Project → **API Keys**
3. Click **Create**, select the target agent
4. Copy the API key (it will be shown once) and store it securely
**Request Header:**
```http
Authorization: Bearer
```
When running the API server locally with `pnpm dev`, authentication is automatically bypassed. You can use headers in the request instead:
**Request Headers:**
```http
x-inkeep-tenant-id:
x-inkeep-project-id:
x-inkeep-agent-id:
```
This mode is for development only. Never use in production as it bypasses all security checks.
See [Authentication → Run API](/api-reference/authentication/run-api) for more details.
>
### Optional Configuration
```tsx
const { messages, sendMessage, status } = useChat({
api: 'http://localhost:3003/api/chat',
headers: { /* ... */ },
// Handle completion
onFinish: (message) => {
console.log('Agent finished responding:', message);
},
// Handle errors
onError: (error) => {
console.error('Chat error:', error);
},
});
```
## Headers
To pass required headers (validated against your Context Config), include them as custom headers:
```tsx
const { messages, sendMessage } = useChat({
api: 'http://localhost:3003/api/chat',
headers: {
'Authorization': `Bearer ${apiKey}`,
// Custom context headers
'x-user-id': 'user-123',
'x-organization-id': 'org-456',
},
});
```
See [Headers](/typescript-sdk/headers) for details.
## Complete Example
Here's a more complete example with conversation management and custom styling:
```tsx
"use client";
import { useChat } from "@ai-sdk/react";
import { DefaultChatTransport } from "ai";
import { useState } from "react";
export default function Page() {
const { messages, sendMessage } = useChat({
transport: new DefaultChatTransport({
api: "{process.env.NEXT_PUBLIC_INKEEP_AGENTS_RUN_API_URL}/api/chat",
headers: {
"x-inkeep-tenant-id": "default",
"x-inkeep-project-id": "activities-planner",
"x-inkeep-agent-id": "activities-planner",
tz: "US/Pacific",
},
}),
});
const [input, setInput] = useState("");
return (
);
}
if (part.type?.startsWith("data-")) {
return (
Data: {JSON.stringify(part, null, 2)}
);
}
return null;
})}
))}
Try asking:
"What's the weather in New York?"
"Can you get my location?"
"Ask me to confirm something"
);
}
```
## Environment Variables
For production deployments, store configuration in environment variables:
```bash
NEXT_PUBLIC_INKEEP_AGENTS_RUN_API_URL=your_domain_for_run_api
NEXT_PUBLIC_INKEEP_API_KEY=your-api-key
NEXT_PUBLIC_TENANT_ID=your-tenant-id
NEXT_PUBLIC_PROJECT_ID=your-project-id
NEXT_PUBLIC_AGENT_ID=your-agent-id
```
In local development, the Run API runs at `http://localhost:3003`. For production, update this to your deployed Run API URL.
## Next Steps
Explore Vercel's prebuilt UI components library built on shadcn/ui for rapid development.
Use prebuilt React components for a complete chat UI experience.
Learn about the underlying HTTP API and streaming protocol.
# Leverage Composio MCP Server Library
URL: /tutorials/mcp-servers/composio-mcp-servers
Connect to Composio MCP servers for 10,000+ out-of-box MCP servers
***
title: Leverage Composio MCP Server Library
sidebarTitle: Composio
description: Connect to Composio MCP servers for 10,000+ out-of-box MCP servers
icon: "brand/Composio"
----------------------
### Composio
[Composio](https://composio.dev/) offers a platform with access to 10,000+ out-of-box MCP servers for popular services.
#### Quick integration
Follow Composio's MCP Gateway setup to obtain your MCP server URL and credentials. Then register it as a tool in your project:
```typescript
import { mcpTool } from '@inkeep/agents-sdk';
const composioTool = mcpTool({
id: 'composio-tools',
name: 'Composio Integration',
description: 'Access popular SaaS tools via Composio',
serverUrl: 'YOUR_COMPOSIO_MCP_URL', // From Composio dashboard
});
```
<>
### Next steps
Once you have your server, you can register it in one of:
Add your MCP server as a tool for your agents in the TypeScript SDK
Add your MCP server as a tool for your agents in the Visual Builder
>
# Build Custom MCP Servers
URL: /tutorials/mcp-servers/custom-mcp-servers
Build your own custom MCP servers
***
title: Build Custom MCP Servers
sidebarTitle: Custom
description: Build your own custom MCP servers
icon: "brand/Inkeep"
--------------------
## When to Build Custom MCP Servers
Build custom MCP servers when:
* Native servers don't exist for your specific APIs
* You need custom business logic beyond what existing servers provide
* You have proprietary systems that require custom integration
If pre-built servers meet your needs, consider [Native MCP servers](/tutorials/mcp-servers/native-mcp-servers), [Composio's platform](/tutorials/mcp-servers/composio-mcp-servers), or [Gram](/tutorials/mcp-servers/gram) instead.
## Getting Started
The Quick Start workspace includes a Next.js app in the `apps/mcp/app/` directory that you can use to expose your MCP servers.
Each MCP server you create will be exposed on a separate route on this app.
#### Creating from a template
You can add a custom MCP server template from our [template library](https://github.com/inkeep/agents/tree/main/agents-cookbook/template-mcps) for common use cases using the [CLI](/typescript-sdk/cli-reference#inkeep-add).
```bash
inkeep add --mcp [server-name]
```
This will automatically add a custom MCP server template to your Quick Start workspace. After customizing and deploying it, you can register it.
#### Using Vercel's Template
If you want to create a custom MCP server, you can use Vercel's [Next.js MCP template](https://vercel.com/templates/next.js/model-context-protocol-mcp-with-next-js) as a starting point:
From the workspace root, add the Vercel template:
```bash
inkeep add --mcp vercel-template
```
Rename the template to your desired server name:
```bash
mv apps/mcp/app/vercel-template apps/mcp/app/[server-name]
```
Update the `basePath` inside `apps/mcp/app/[server-name]/mcp/route.ts` to `/[server-name]`:
```typescript
{
basePath: "/[server-name]",
verboseLogs: true,
maxDuration: 60,
disableSse: true,
}
```
Customize the template with your desired tools.
You can access the server at `http://localhost:3006/[server-name]/mcp`. Register it with your agents using the `mcpTool` function.
```typescript
import { mcpTool } from '@inkeep/agents-sdk';
export const mcpTool = mcpTool({
id: '[server-name]',
name: '[server-name]',
description: '[server-name] API',
serverUrl: 'http://localhost:3006/[server-name]/mcp',
});
```
Or you register the MCP server as a tool in the Visual Builder (see [here](/visual-builder/tools/mcp-servers#register-an-mcp-server)).
#### Deploying to Vercel
Follow the instructions in [Deploy to Vercel](/self-hosting/vercel#step-9-create-a-vercel-project-for-your-mcp-server-optional).
If you have already deployed to Vercel, you can simply update the deployment by pushing to the same repository.
Enable Fluid compute and set `maxDuration` to 800 in `apps/mcp/app/[server-name]/[transport]/route.ts` if you're on a Pro or Enterprise plan and have long-running operations.
<>
### Next steps
Once you have your server, you can register it in one of:
Add your MCP server as a tool for your agents in the TypeScript SDK
Add your MCP server as a tool for your agents in the Visual Builder
>
# Create an OpenAPI-based MCP server
URL: /tutorials/mcp-servers/gram
undefined
***
title: Create an OpenAPI-based MCP server
sidebarTitle: Gram
icon: "brand/Gram"
------------------
## Overview
Gram by Speakeasy turns any OpenAPI specification into a production-ready MCP server. Upload your API spec, and Gram automatically generates tool definitions, handles hosting and authentication, and deploys your server- so you can focus on building powerful agents.
Visit [Gram's documentation](https://www.speakeasy.com/docs/gram/getting-started/openapi) for a complete guide.
For custom MCP server logic, use [Gram Functions](https://www.speakeasy.com/docs/gram/getting-started/typescript), Gram's TypeScript framework with managed deployment and hosting.
### Step 1: Sign up for a Gram account
[Sign up](https://app.getgram.ai/login) for a free Gram account.
### Step 2: Upload your OpenAPI document
Navigate to **Toolsets** in the Gram dashboard sidebar (under **Create**) and click **Get Started**
Upload your OpenAPI document, provide a descriptive name, and click **Upload**
Gram extracts URL paths, HTTP methods, request schemas, and operation descriptions from your OpenAPI document to generate tool definitions.
Gram works with partial OpenAPI documents as long as key elements (paths, methods, schemas, descriptions) are present.
### Step 3: Ship 🚢
Your MCP server is ready to ship! Open the MCP page, and open your MCP server by clicking it. Click Enable to allow the MCP server to handle requests.
### Step 4: Add authentication (optional)
To add authentication, set the appropriate environment variables. See [Step 3 in the Gram documentation](https://www.speakeasy.com/docs/gram/getting-started/openapi#step-3-set-environment-variables) for details.
<>
### Next steps
Once you have your server, you can register it in one of:
Add your MCP server as a tool for your agents in the TypeScript SDK
Add your MCP server as a tool for your agents in the Visual Builder
>
# Connect to Native MCP Servers
URL: /tutorials/mcp-servers/native-mcp-servers
Connect to Native MCP servers provided by SaaS vendors
***
title: Connect to Native MCP Servers
sidebarTitle: Native
description: Connect to Native MCP servers provided by SaaS vendors
icon: "LuPackageCheck"
----------------------
The fastest way to get started is by connecting to existing MCP servers provided directly by SaaS providers that offer them.
### MCPs with OAuth 2.1/PKCE support
These servers often implement OAuth 2.1 with PKCE for secure authentication that allow for `1-click` authentication without the need for API keys.
<>
Here's an example list of popular service-maintained MCP Servers that support **1-click** install via the OAuth 2.1/PKCE authentication flow.
| Name | URL |
| ---------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- |
| [Atlassian (SSE)](https://support.atlassian.com/rovo/docs/getting-started-with-the-atlassian-remote-mcp-server/) | [https://mcp.atlassian.com/v1/sse](https://mcp.atlassian.com/v1/sse) |
| [Canva](https://www.canva.dev/docs/connect/canva-mcp-server-setup/) | [https://mcp.canva.com/mcp](https://mcp.canva.com/mcp) |
| [Hugging Face](https://huggingface.co/mcp) | [https://huggingface.co/mcp?login](https://huggingface.co/mcp?login) |
| [Intercom](https://developers.intercom.com/docs/guides/mcp) | [https://mcp.intercom.com/mcp](https://mcp.intercom.com/mcp) |
| [Linear](https://linear.app/docs/mcp) | [https://mcp.linear.app/mcp](https://mcp.linear.app/mcp) |
| [Neon](https://neon.com/docs/ai/neon-mcp-server) | [https://mcp.neon.tech/mcp](https://mcp.neon.tech/mcp) |
| [Notion](https://developers.notion.com/docs/get-started-with-mcp) | [https://mcp.notion.com/mcp](https://mcp.notion.com/mcp) |
| [Prisma](https://www.prisma.io/docs/postgres/integrations/mcp-server#remote-mcp-server) | [https://mcp.prisma.io/mcp](https://mcp.prisma.io/mcp) |
| [Sentry](https://docs.sentry.io/product/sentry-mcp/) | [https://mcp.sentry.dev/mcp](https://mcp.sentry.dev/mcp) |
| [Vercel](https://vercel.com/docs/mcp/vercel-mcp) | [https://mcp.vercel.com](https://mcp.vercel.com) |
To add them to your project:
1. navigate to **MCP Servers** in the Inkeep Visual Builder.
2. Click on **New MCP Server**
3. Choose from the preset list under **Popular Services** or register any under **Custom Server**
When you register the server, an authentication pop-up will appear and allow you to sign in. Your credentials will automatically be saved to your [Nango Store](/typescript-sdk/credentials/nango) or [Keychain](/typescript-sdk/credentials/keychain) credential store.
>
<>
### Next steps
Once you have your server, you can register it in one of:
Add your MCP server as a tool for your agents in the TypeScript SDK
Add your MCP server as a tool for your agents in the Visual Builder
>
# MCP Server Options
URL: /tutorials/mcp-servers/overview
Learn about the recommended ways to use MCP servers with your agents
***
title: MCP Server Options
sidebarTitle: Overview
description: Learn about the recommended ways to use MCP servers with your agents
icon: "LuSparkles"
------------------
MCP servers enable your agents to fetch real-time information and take action on your systems, services, and applications.
## Choose your approach
Select the option that best fits your needs:
* **Native MCP Servers** - Pre-built servers from SaaS vendors (Atlassian, Linear, Notion, etc.). Fastest setup, just register and go.
* **Composio MCP Servers** - Access 10,000+ pre-built servers through Composio's platform. Similar to Native, but with a wider selection.
* **Custom MCP Servers** - Build your own servers for custom APIs and business logic. Requires development and deployment.
* **Gram by Speakeasy** - Convert OpenAPI specs into MCP servers using Gram by Speakeasy.
## Get started
Connect to pre-built servers from providers like Atlassian, Linear, Notion, and more. No building required.
Access thousands of out-of-box MCP servers through Composio's platform.
Build your own custom MCP servers using Inkeep templates or Vercel's Next.js template.
Convert OpenAPI specs into MCP servers using Gram by Speakeasy.
# Environment-aware Credentials
URL: /typescript-sdk/credentials/env-aware-credentials
undefined
***
title: Environment-aware Credentials
sidebarTitle: Env-aware Credentials
icon: "LuLayers"
----------------
Environment-aware credentials enable automatic loading of environment-specific credentials (development, production, etc.) while keeping them cleanly separated and easily switchable via the CLI's --env flag.
Credentials are referenced in the TypeScript SDK using the `envSettings` object. Creating environment-aware credentials is a two step process:
### Step 1: Define environment configurations
```typescript title="projects/my-project/environments/development.env.ts"
import { registerEnvironmentSettings } from '@inkeep/agents-sdk';
import { CredentialStoreType } from '@inkeep/agents-core';
// How credentials are referenced depends on how the credential was created, in this case this credential was created as an environment variable
export const development = registerEnvironmentSettings({
credentials: {
'stripe_api_key': {
id: 'stripe-api-key',
name: 'Stripe API Key',
type: CredentialStoreType.memory,
credentialStoreId: 'memory-default',
retrievalParams: {
key: 'STRIPE_API_KEY_DEV',
},
}
},
});
```
```typescript title="projects/my-project/environments/production.env.ts"
import { registerEnvironmentSettings } from '@inkeep/agents-sdk';
import { CredentialStoreType } from '@inkeep/agents-core';
// How credentials are referenced depends on how the credential was created, in this case this credential was created as an environment variable
export const production = registerEnvironmentSettings({
credentials: {
'stripe_api_key': {
id: 'stripe-api-key',
name: 'Stripe API Key',
type: CredentialStoreType.memory,
credentialStoreId: 'memory-default',
retrievalParams: {
key: 'STRIPE_API_KEY_PROD',
},
}
},
});
```
```typescript title="projects/my-project/environments/index.ts"
import { createEnvironmentSettings } from '@inkeep/agents-sdk';
import { development } from './development.env';
import { production } from './production.env';
export const envSettings = createEnvironmentSettings({
development,
production,
});
```
### Step 2: Use the credentials in tools
```typescript title="/tools/stripe-tool.ts"
import { mcpTool } from "@inkeep/agents-sdk";
import { envSettings } from "../environments";
export const stripeTool = mcpTool({
id: 'stripe-tool',
name: 'Stripe',
serverUrl: 'https://mcp.stripe.com/mcp',
credential: envSettings.getEnvironmentCredential('stripe_api_key'),
});
```
This pattern is useful if you want to keep track of different credentials for different environments. When you push your project using the [Inkeep CLI](/typescript-sdk/cli-reference#inkeep-push) `inkeep push` command with the `--env` flag, the credentials will be loaded from the appropriate environment file. For example, if you run `inkeep push --env development`, the credentials will be loaded from the `environments/development.env.ts` file.
### CLI Environment Variables
The CLI respects these environment variables when using the `--env` flag:
```bash
# Set environment name via environment variable
export INKEEP_ENV=production
inkeep push # Uses production environment automatically
# Override via CLI (takes precedence)
inkeep push --env development # Uses development instead
```
# Use Environment Variables as Credentials
URL: /typescript-sdk/credentials/environment-variables
undefined
***
title: Use Environment Variables as Credentials
sidebarTitle: Environment Variables
icon: "LuDatabase"
------------------
Environment variables are a simple way to store credentials in your environment. They are stored in the environment variables in your `.env` file.
## Referencing credentials in SDK
Here is an example of how to reference a credential in the TypeScript SDK for Bearer Authentication.
```typescript
import { agent, subAgent, mcpTool, credential } from "@inkeep/agents-sdk";
import { CredentialStoreType } from "@inkeep/agents-core";
// Step 1: Reference the credential created in the environment file
const stripeCredential = credential({
id: 'stripe-credential',
name: 'Stripe Credential',
type: CredentialStoreType.memory,
credentialStoreId: 'memory-default',
retrievalParams: {
"key": "", // where is the name of the environment variable that contains the credential value, for example, STRIPE_API_KEY
},
});
// Step 2: Use credential in MCP tool
const stripeTool = mcpTool({
id: 'stripe-tool',
name: 'Stripe Tool',
description: 'Access Stripe payment services',
serverUrl: 'https://mcp.stripe.com/mcp',
credential: stripeCredential,
});
```
### Credential Configuration
| Parameter | Type | Required | Description |
| ------------------- | ------------------- | -------- | -------------------------------------------------------- |
| `id` | string | Yes | Unique identifier for the credential |
| `type` | CredentialStoreType | Yes | Type of credential store (memory, nango, or keychain) |
| `credentialStoreId` | string | Yes | Identifier for the specific credential store instance |
| `retrievalParams` | object | Yes | Parameters for retrieving the credential from the store. |
# Use Keychain for Local Development
URL: /typescript-sdk/credentials/keychain
undefined
***
title: Use Keychain for Local Development
sidebarTitle: Keychain
icon: "LuLock"
--------------
Keychain is the default method for storing credentials for every project. It is a locally stored credential store for OAuth tokens from OAuth2.1/PKCE flows and Bearer authentication, configured through Visual Builder and referenced in the TypeScript SDK.
Keychain lacks automatic token refresh, production suitability, and metadata header support, making Nango the recommended solution for production-ready credential management. See setup instructions for Nango [here](/typescript-sdk/credentials/nango).
## Referencing credentials in SDK
Here is an example of how to reference a credential in the TypeScript SDK for both Bearer Authentication and OAuth2.1/PKCE.
```typescript
import { agent, subAgent, mcpTool, credential } from "@inkeep/agents-sdk";
import { CredentialStoreType } from "@inkeep/agents-core";
// Step 1: Reference the credential created in the Visual Builder
const stripeCredential = credential({
id: 'stripe-credential',
name: 'Stripe Credential',
type: CredentialStoreType.memory,
credentialStoreId: 'memory-default',
retrievalParams: {
"key": "" // where is the id given to the bearer api key created through the Visual Builder
},
});
// Step 2: Use credential in MCP tool
const stripeTool = mcpTool({
id: 'stripe-tool',
name: 'Stripe Tool',
description: 'Access Stripe payment services',
serverUrl: 'https://mcp.stripe.com/mcp',
credential: stripeCredential,
});
```
```typescript
import { agent, subAgent, mcpTool, credential } from "@inkeep/agents-sdk";
import { CredentialStoreType } from "@inkeep/agents-core";
// Step 1: Reference the credential created in the Visual Builder
const stripeCredential = credential({
id: 'stripe-credential',
name: 'Stripe Credential',
type: CredentialStoreType.memory, // Memory store
credentialStoreId: 'memory-default',
retrievalParams: {
"key": "oauth_token_" // where is the id of the MCP tool the credential is associated with
},
});
// Step 2: Use credential in MCP tool
const stripeTool = mcpTool({
id: 'stripe-tool',
name: 'Stripe Tool',
description: 'Access Stripe payment services',
serverUrl: 'https://mcp.stripe.com/mcp',
credential: stripeCredential,
});
```
### Credential Configuration
| Parameter | Type | Required | Description |
| ------------------- | ------------------- | -------- | -------------------------------------------------------- |
| `id` | string | Yes | Unique identifier for the credential |
| `type` | CredentialStoreType | Yes | Type of credential store (memory, nango, or keychain) |
| `credentialStoreId` | string | Yes | Identifier for the specific credential store instance |
| `retrievalParams` | object | Yes | Parameters for retrieving the credential from the store. |
# Use Nango as a Credential Store
URL: /typescript-sdk/credentials/nango
undefined
***
title: Use Nango as a Credential Store
sidebarTitle: Nango
icon: "brand/Nango"
-------------------
Nango is an excellent choice for both development and production environments, particularly when working with OAuth2.1/PKCE flows and complex integrations.
To get started, first set up Nango either through cloud or local deployment, then create your credential, and finally consume the credential through the TypeScript SDK.
## Nango setup option 1: Nango Cloud
### Step 1: Create a Nango account
Sign up [here](https://app.nango.dev/signin).
### Step 2: Save your Nango secret key
After creating your Nango account, navigate to Environment Settings in your dashboard and copy the secret key.
### Step 3: Configure your root `.env` file
```
NANGO_SECRET_KEY=your_nango_secret_key
```
Restart your dev server to load the new environment variable:
```bash
pnpm dev
```
### Step 4: Create a new credential in the Visual Builder using Nango
## Nango setup option 2: Nango local
### Step 1: Clone the optional services repository
```bash
git clone https://github.com/inkeep/agents-optional-local-dev
cd agents-optional-local-dev
```
### Step 2: Start Nango Services
Inside the `agents-optional-local-dev` repository, run the following command:
```bash
docker-compose --profile nango up -d
```
### Step 3: Save your Nango secret key
1. Open Nango at `http://localhost:3050`
2. Navigate to Environment Settings and copy the secret key
### Step 4: Configure your root `.env` file
In your **root project directory** (not inside the `agents-optional-local-dev` repository), update your `.env` file:
```bash
NANGO_SECRET_KEY=your_nango_secret_key
NANGO_HOST=http://localhost:3050
PUBLIC_NANGO_CONNECT_BASE_URL=http://localhost:3051
```
Restart your dev server to load the new environment variables:
```bash
pnpm dev
```
### Step 5: Create a new credential in the Visual Builder using Nango
Create a new credential in the [Visual Builder](/visual-builder/credentials) using Nango Store as the credential store.
## Referencing credentials in SDK
Once you have created a credential in the Visual Builder, you can reference it in the TypeScript SDK for both Bearer Authentication and OAuth2.1/PKCE.
Here is an example of how to reference a credential in the TypeScript SDK for both Bearer Authentication and OAuth2.1/PKCE.
```typescript
import { agent, subAgent, mcpTool, credential } from "@inkeep/agents-sdk";
import { CredentialStoreType } from "@inkeep/agents-core";
// Step 1: Reference the credential created in the Visual Builder
const stripeCredential = credential({
id: 'stripe-credential',
name: 'Stripe Credential',
type: CredentialStoreType.memory,
credentialStoreId: 'memory-default',
retrievalParams: {
"connectionId": "", // where is the id given to the bearer api key created through the Visual Builder
"providerConfigKey": "",
"provider": "private-api-bearer",
"authMode": "API_KEY"
},
});
// Step 2: Use credential in MCP tool
const stripeTool = mcpTool({
id: 'stripe-tool',
name: 'Stripe Tool',
description: 'Access Stripe payment services',
serverUrl: 'https://mcp.stripe.com/mcp',
credential: stripeCredential,
});
```
```typescript
import { agent, subAgent, mcpTool, credential } from "@inkeep/agents-sdk";
import { CredentialStoreType } from "@inkeep/agents-core";
// Step 1: Reference the credential created in the Visual Builder
const stripeCredential = credential({
id: 'stripe-credential',
name: 'Stripe Credential',
type: CredentialStoreType.memory, // Memory store
credentialStoreId: 'memory-default',
retrievalParams: {
"connectionId": "", // Nango connection ID that was generated. You can confirm this in your nango dashboard (cloud or self-hosted)
"providerConfigKey": "_", // For example, linear_AABBCC1234
"provider": "mcp-generic",
"authMode": "OAUTH2"
},
});
// Step 2: Use credential in MCP tool
const stripeTool = mcpTool({
id: 'stripe-tool',
name: 'Stripe Tool',
description: 'Access Stripe payment services',
serverUrl: 'https://mcp.stripe.com/mcp',
credential: stripeCredential,
});
```
### Credential Configuration
| Parameter | Type | Required | Description |
| ------------------- | ------------------- | -------- | -------------------------------------------------------- |
| `id` | string | Yes | Unique identifier for the credential |
| `type` | CredentialStoreType | Yes | Type of credential store (memory, nango, or keychain) |
| `credentialStoreId` | string | Yes | Identifier for the specific credential store instance |
| `retrievalParams` | object | Yes | Parameters for retrieving the credential from the store. |
# Credential Store Options
URL: /typescript-sdk/credentials/overview
undefined
***
title: Credential Store Options
sidebarTitle: Overview
icon: "LuSparkles"
------------------
## Credential Store Options
MCP servers and external agents may require authentication for secure access. The Inkeep agent framework supports storing these credentials in three different ways:
**Best for:** Development or Production environments with OAuth2.1/PKCE flows and complex integrations
**Pros:**
* Automatic token refresh for OAuth
* Supports additional metadata headers
* Works with complex OAuth flows (OAuth2.0/PKCE)
* Managed service (self-hosted or cloud)
**Best for:** Local development with OAuth services
**Cons:**
* Not suitable for production
* No automatic token refresh
* Requires manual re-authentication when tokens expire
* Does not support additional metadata headers
**Best for:** Simple API keys and bearer tokens in development or production
**Pros:**
* Direct configuration via TypeScript SDK
**Cons:**
* Does not support additional metadata headers
* Does not support OAuth2.1/PKCE flows
## Environment-aware Credentials
When you need different credentials for different environments (e.g., development vs. production), you can take advantage of [environment-aware credentials](/typescript-sdk/credentials/env-aware-credentials). This approach allows you to:
* Define separate credentials for each environment
* Automatically load the correct credentials based on your deployment environment
* Keep your development and production credentials cleanly separated
* Easily switch between environments using the CLI's `--env` flag
Learn more about setting up environment-aware credentials in the [dedicated guide](/typescript-sdk/credentials/env-aware-credentials).
# Artifact Components
URL: /typescript-sdk/structured-outputs/artifact-components
Learn how to use artifact components to store and retrieve data from the agent
***
title: Artifact Components
description: Learn how to use artifact components to store and retrieve data from the agent
icon: "TbInputSpark"
--------------------
<>
Artifacts are structured components that capture and store source information when agents interact with tools or other agents. They act as a record-keeping system, automatically documenting where information comes from during tool and agent interactions.
## How Artifacts Work
When an agent uses a tool (whether that's another agent or a utility tool), the response is automatically parsed to create artifacts. These artifacts store:
* The source of the information (tool/agent used)
* The relevant content from the response
* Metadata about the interaction
>
## Defining Artifact Components
Artifact components are defined using the `artifactComponent` builder function. **We recommend using Zod schemas** for type safety and better developer experience.
**Quick Start**: Citation artifacts are automatically included when you create
a new project with `npx @inkeep/create-agents`, providing a ready-to-use
example.
```typescript
import { artifactComponent } from "@inkeep/agents-sdk";
import { z } from "zod";
import { preview } from "@inkeep/agents-core";
export const citation = artifactComponent({
id: "citation",
name: "citation",
description: "Structured factual information extracted from search results",
props: z.object({
title: preview(z.string().describe("Title of the source document")),
url: preview(z.string().describe("URL of the source document")),
record_type: preview(
z.string().describe("Type of record (documentation, blog, guide, etc.)")
),
content: z
.array(
z.object({
type: z
.string()
.describe("Type of content (text, image, video, etc.)"),
text: z.string().describe("The actual text content"),
})
)
.describe(
"Array of structured content blocks extracted from the document"
),
}),
});
```
JSON Schema is also supported. Set `inPreview: true` on properties instead of
using `preview()`.
## Schema Requirements
**Critical**: Artifact schemas must match your tool's output structure. The
system uses JMESPath selectors on JSON - it **cannot extract from free text**.
```typescript
// ❌ WRONG: Tool returns text, schema expects structured data
// Tool output: { result: { content: [{ text: "Weather: Sunny, 75°F" }] } }
props: z.object({
temperature: z.number(), // ❌ Cannot extract number from text
condition: z.string(), // ❌ Cannot extract condition from text
});
// ✅ CORRECT: Tool returns structured data matching schema
// Tool output: { result: { temperature: 75, condition: "Sunny" } }
props: z.object({
temperature: z.number(),
condition: z.string(),
});
```
Use OpenTelemetry traces to debug schema validation issues.
## Preview Fields
Use `preview()` to mark fields for immediate availability. The `preview()` helper automatically sets `inPreview: true` in the generated schema.
**Preview fields are:**
* Shown to other agents for reasoning
* Streamed in real-time to clients (Vercel AI SDK)
* Auto-rendered by Inkeep's widget (citations as interactive cards)
* Available immediately in UI (full artifact loads on-demand)
**Non-preview fields** require explicitly fetching the full artifact.
**No schema?** Omit `props` to save the entire tool result without filtering.
## Artifact Creation
When an agent uses a tool:
1. The tool processes the request and returns a response
2. **The agent decides** whether to create an artifact from the tool response
3. If created, the artifact is parsed according to the artifact component schema
4. The artifact can be associated with any data components that reference this information
## Artifacts vs Data Components
**Artifacts** and **Data Components** are different:
* **Artifacts**: Citations/sources from tool results stored in the database
* **Data Components**: UI elements agents output in responses (Text, Fact, etc.)
Artifacts provide the source citations that back up information in data components.
## Using in Agents
After defining your artifact component, use it in an agent:
```typescript
import { agent } from "@inkeep/agents-sdk";
import { citation } from "./artifact-components/citation";
const searchAgent = agent({
id: "search-agent",
canUse: () => [searchTool],
prompt: "Search for information and cite sources using artifacts.",
artifactComponents: () => [citation],
});
```
## Citation Artifacts
Citation artifacts that are named `citation` and have `title` and `url` preview fields are automatically rendered as interactive cards by Inkeep's widget library. This provides source attribution and allows users to verify information at the source.
## Example Flow
Here's a complete example with inline artifact component definition:
```typescript
import { agent } from "@inkeep/agents-sdk";
import { z } from "zod";
import { preview } from "@inkeep/agents-core";
const searchAgent = subAgent({
id: "search",
canUse: () => [searchTool],
prompt: "Search for information and cite sources using artifacts.",
artifactComponents: [
{
id: "citation",
name: "citation",
description: "Search result document",
props: z.object({
title: preview(z.string().describe("Document title")),
url: preview(z.string().describe("Document URL")),
content: z.string().describe("Document content"),
}),
},
],
});
```
## No Schema Example
```typescript
const rawDataAgent = subAgent({
id: "raw-data",
canUse: () => [apiTool],
prompt: "Fetch data and save complete responses.",
artifactComponents: [
{
id: "api-response",
name: "API Response",
description: "Complete API response data",
// No props - saves entire tool result
},
],
});
```
Example flow:
1. Agent uses search tool and gets results
2. **Agent decides** to create an artifact citing the source document
3. Artifact is stored with preview fields (title, url) shown to other agents
4. Other agents can reference this artifact or get full content when needed
# Create Rich UI Blocks with Data Components
URL: /typescript-sdk/structured-outputs/data-components
Learn how to create and use data components for rich, interactive Agent messages.
***
title: Create Rich UI Blocks with Data Components
sidebarTitle: Custom UI Blocks
description: Learn how to create and use data components for rich, interactive Agent messages.
icon: "LuBlocks"
----------------
<>
## What are Data Components?
Data Components allow your agents to return rich, interactive content instead of just text. Think of them as reusable UI building blocks that your agent can populate with data.
For example, instead of returning "You have 3 tasks: Task #123 (shipped), Task #124 (processing)...", your agent can return a properly formatted task list component.
>
## Defining Data Components
Data components are defined using the `dataComponent` builder function. **We recommend using Zod schemas** for type safety and better developer experience.
```typescript
import { dataComponent } from '@inkeep/agents-sdk';
import { z } from 'zod';
export const taskList = dataComponent({
id: "task-list",
name: "TaskList",
description: "Display user tasks with status",
props: z.object({
tasks: z
.array(
z.object({
id: z.string().describe("Unique task identifier"),
title: z.string().describe("Task title"),
completed: z.boolean().describe("Whether the task is completed"),
priority: z.enum(["low", "medium", "high"]).describe("Task priority"),
})
)
.describe("Array of user tasks"),
totalCount: z.number().describe("Total number of tasks"),
completedCount: z.number().describe("Number of completed tasks"),
}),
});
```
JSON Schema is also supported if you prefer traditional schema definitions.
## Using in Agents
Register data components with your agent:
```typescript
import { agent } from '@inkeep/agents-sdk';
import { taskList } from './data-components/task-list';
const taskAgent = agent({
id: "task-agent",
name: "Task Agent",
prompt: "Provide helpful answers and use data components when appropriate.",
dataComponents: () => [taskList],
});
```
When a user asks "Show me my tasks", the agent will respond with:
```json
{
"dataComponents": [
{
"id": "task-list",
"name": "TaskList",
"props": {
"tasks": [
{ "id": "1", "title": "Review documentation", "completed": false },
{ "id": "2", "title": "Update website", "completed": true }
]
}
}
]
}
```
## Frontend Integration
Create a React component matching your data component name:
```tsx
const TaskList = ({ tasks, totalCount, completedCount }) => (
Your Tasks ({completedCount}/{totalCount} completed)
{tasks.map((task) => (
{task.title}
))}
);
```
Register it with the Inkeep chat component:
```tsx
```
The agent will automatically return structured data that renders as your React component.
# Status Updates
URL: /typescript-sdk/structured-outputs/status-updates
Real-time progress updates powered by AI that keep users informed during long-running agent operations
***
title: Status Updates
description: Real-time progress updates powered by AI that keep users informed during long-running agent operations
icon: "LuClock"
---------------
import { Callout } from "fumadocs-ui/components/callout";
# Status Updates
The Inkeep Agent Framework provides intelligent, AI-powered status updates that automatically generate contextual progress messages during agent execution. These updates give users ChatGPT-style feedback about what's happening behind the scenes without exposing internal technical details.
## Overview
Status updates are automatically generated summaries that:
* **Track Progress**: Monitor agent operations, tool calls, and task completions
* **Provide Context**: Generate user-friendly descriptions of what's happening
* **Hide Complexity**: Abstract away internal agent names and technical operations
* **Stream Real-time**: Send updates via the same streaming interface as responses
Status updates use your Agent's summarizer model to generate contextual,
intelligent progress messages that feel natural to users.
## How It Works
The status updater operates through three main components:
### 1. Agent Session Event Tracking
Every agent operation is tracked as events:
* **agent\_generate**: Text generation or structured output
* **transfer**: Agent-to-agent transfers
* **delegation\_sent/returned**: Task delegation between agents
* **tool\_call**: When a tool is called with arguments
* **tool\_result**: When a tool execution completes (success or failure)
* **error**: System-level errors and configuration issues
* **artifact\_saved**: Document or data artifacts created
### 2. Intelligent Triggering
Status updates are triggered by:
* **Event Count**: After N events (tool calls, generations, etc.)
* **Time Intervals**: Every N seconds of processing
* **Smart Detection**: Avoids updates during text streaming
### 3. AI-Powered Summarization
The summarizer model:
* Analyzes recent events and progress
* Generates user-friendly status messages
* Maintains context across multiple updates
* Focuses on user-visible outcomes
## Configuration
Configure status updates in your agent:
```typescript
export const myAgent = agent({
id: "my-agent",
defaultSubAgent: myAgent,
subAgents: () => [myAgent],
// Model Settings with summarizer
models: {
base: { model: "anthropic/claude-sonnet-4-5" },
summarizer: { model: "anthropic/claude-sonnet-4-5" }, // Model for status updates
},
// Status updates configuration
statusUpdates: {
numEvents: 3, // Trigger after 3 events
timeInSeconds: 15, // Trigger every 15 seconds
prompt: "Custom prompt for status updates", // Optional
},
});
```
### Configuration Options
| Option | Type | Default | Description |
| ------------------ | ------ | ------------- | ------------------------------------------------------------- |
| `numEvents` | number | 10 | Trigger update after N events |
| `timeInSeconds` | number | 30 | Trigger update every N seconds |
| `model` | string | agent default | Override model for summaries |
| `prompt` | string | undefined | Custom prompt appended to base system prompt (max 2000 chars) |
| `statusComponents` | array | undefined | Structured status components (advanced) |
## Basic Example
```typescript
const searchAgent = subAgent({
id: "search-agent",
name: "Search Agent",
prompt: "Help users search and analyze information.",
canUse: () => [searchTool],
});
export const searchDemo = agent({
id: "search-demo",
defaultSubAgent: searchAgent,
subAgents: () => [searchAgent],
models: {
base: { model: "anthropic/claude-sonnet-4-5" },
summarizer: { model: "anthropic/claude-sonnet-4-5" },
},
// Enable status updates
statusUpdates: {
numEvents: 2, // Update every 2 operations
timeInSeconds: 10, // Or every 10 seconds
},
});
```
**User Experience:**
When a user asks "What's the weather in Paris?", they might see:
1. "Searching for current weather information..."
2. "Found weather data, analyzing conditions..."
3. "Preparing detailed weather report..."
## Custom Prompts
You can customize how status updates are generated by providing a custom prompt that gets appended to the base system prompt. Custom prompts are limited to 2000 characters to ensure optimal performance:
```typescript
export const myAgent = agent({
id: "my-agent",
defaultSubAgent: myAgent,
subAgents: () => [myAgent],
models: {
summarizer: { model: "anthropic/claude-sonnet-4-5" },
},
statusUpdates: {
numEvents: 3,
timeInSeconds: 15,
// Custom prompt is appended to the base system prompt
prompt: "KEEP ALL STATUS UPDATES SHORT AND CONCISE. Use bullet points and focus only on user-visible progress.",
},
});
```
### Custom Prompt Examples
**Concise Updates:**
```typescript
statusUpdates: {
prompt: 'Keep responses to 5 words maximum. Use present tense verbs.',
}
// Results in: "Searching documentation", "Processing data", "Generating report"
```
**Detailed Progress:**
```typescript
statusUpdates: {
prompt: 'Provide specific details about what was found or accomplished. Include relevant numbers or names when available.',
}
// Results in: "Found 12 API endpoints in authentication docs", "Retrieved user profile for john@example.com"
```
**Branded Tone:**
```typescript
statusUpdates: {
prompt: 'Use a friendly, helpful tone. Start updates with action words like "Discovering", "Exploring", "Analyzing".',
}
// Results in: "Discovering relevant documentation...", "Analyzing search results for best matches"
```
## Default vs Structured Status Updates
Status updates can be generated in two ways:
### Default Status Components
When no `statusComponents` are configured, the system uses built-in default status components that generate structured labels with contextual details:
* **`label`**: AI-generated user-friendly description (e.g., "Searching documentation for API examples")
* **`details`**: Optional structured data with context about the operation
The default status components are defined in [`packages/agents-sdk/src/default-status-schemas.ts`](https://github.com/inkeep/agents/blob/main/packages/agents-sdk/src/default-status-schemas.ts):
```typescript
// Error loading local file from agents-run-api/src/utils/default-status-schemas.ts
// ENOENT: no such file or directory, open '/vercel/path0/agents-docs/agents-run-api/src/utils/default-status-schemas.ts'
```
### Custom Structured Components
For complete control over status format, define custom structured status components using Zod schemas with the `statusComponent` helper:
```typescript
import { z } from 'zod';
import { statusComponent } from '@inkeep/agents-sdk';
const toolSummary = statusComponent({
type: 'tool_summary',
description: 'Summary of tool calls and their purpose',
detailsSchema: z.object({
tool_name: z.string().describe('Name of tool used'),
purpose: z.string().describe('Why this tool was called'),
outcome: z.string().describe('What was discovered or accomplished'),
}),
});
const progressUpdate = statusComponent({
type: 'progress_update',
description: 'Progress information with metrics',
detailsSchema: z.object({
current_step: z.string(),
items_processed: z.number().optional(),
status: z.enum(['in_progress', 'completed', 'pending']),
}),
});
export const myAgent = agent({
id: "my-agent",
defaultSubAgent: myAgent,
subAgents: () => [myAgent],
models: {
summarizer: { model: "anthropic/claude-sonnet-4-5" },
},
statusUpdates: {
numEvents: 3,
timeInSeconds: 15,
statusComponents: [
toolSummary.config,
progressUpdate.config,
],
},
});
```
The `statusComponent` helper provides type-safe status component definitions with automatic schema validation. Zod schemas are automatically converted to JSON Schema format at runtime.
### Status Component API
The `statusComponent` function accepts:
| Property | Type | Required | Description |
| --------------- | ------------------ | -------- | --------------------------------------------------- |
| `type` | string | Yes | Unique identifier for this status component type |
| `description` | string | No | Description of when/why this status is used |
| `detailsSchema` | `z.ZodObject` | No | Zod schema defining the structure of status details |
**Note:** Use `.config` when passing status components to the agent configuration
## Frontend Integration
Status updates arrive as `data-summary` events with AI-generated labels and contextual details:
```typescript
// In your message processing
message.parts.forEach((part) => {
if (part.type === "data-summary") {
const { type, label, details } = part.data;
// Display the user-friendly status label
displayStatusUpdate(label);
// Handle optional structured details
if (details) {
// For default status components: contextual operation details
// For custom components: your defined schema structure
displayStructuredDetails(details);
}
// The 'type' field indicates the summary category
console.log(`Status update type: ${type}`);
}
});
```
### Data Structure Examples
**Custom Status Components:**
```json
{
"type": "tool_summary",
"label": "Search completed successfully",
"details": {
"tool_name": "search_knowledge_base",
"purpose": "Find API authentication documentation",
"outcome": "Found 5 relevant articles with code examples"
}
}
```
## Best Practices
### Timing Configuration
* **Quick Operations**: Use higher event counts (5-10) to avoid too many updates
* **Long Operations**: Use shorter time intervals (10-15 seconds) for responsiveness
* **Mixed Workloads**: Combine both triggers for balanced updates
### Model Selection
* **Faster Model**: Use a faster/cheaper model for status updates to reduce latency
* **Specialized Model**: Use a model optimized for summarization tasks
### User Experience
```typescript
// Good: Descriptive and actionable
"Searching through documentation to find API authentication methods...";
"Found OAuth2 setup prompt, now checking for code examples...";
// Avoid: Too technical or vague
"Agent thinking...";
"Processing data-operation with tool_invocation type...";
```
## Troubleshooting
### Updates Not Appearing
Check that:
1. Status updates are configured in your Agent
2. The summarizer model is specified
3. Events are being triggered (tool calls, generations)
4. The session hasn't ended prematurely
### Too Many/Few Updates
Adjust thresholds:
```typescript
statusUpdates: {
numEvents: 5, // Increase for fewer updates
timeInSeconds: 20, // Increase for less frequent updates
}
```
### Poor Update Quality
Improve with custom prompts:
```typescript
statusUpdates: {
numEvents: 3,
timeInSeconds: 15,
prompt: `Generate a brief, user-friendly status update that explains what has been accomplished and what is currently happening. Focus on user-visible progress, not internal operations. Be specific about findings, not just actions.`
}
```
Status updates are automatically paused during text streaming to avoid
interrupting the response flow.
## Performance Considerations
* Status updates use additional model calls - consider costs for high-volume applications
* Updates are generated asynchronously and won't block main agent operations
# Function Tools
URL: /typescript-sdk/tools/function-tools
Create custom JavaScript functions that your agents can execute in secure sandboxes
***
title: Function Tools
description: Create custom JavaScript functions that your agents can execute in secure sandboxes
icon: "LuCode"
--------------
Function tools allow you to create custom JavaScript functions that agents can execute in secure, isolated sandboxes. Unlike [MCP servers](/typescript-sdk/tools/mcp-servers) that connect to external services, function tools run your own code directly within the agent framework.
## Overview
Function tools are perfect for:
* **Custom business logic** - Implement domain-specific calculations or workflows
* **Data processing** - Transform, validate, or analyze data using JavaScript
* **API integrations** - Make HTTP calls to services that don't have MCP servers
* **Utility functions** - Create reusable helper functions for your agents
## Creating Function Tools
### Basic Function Tool
```typescript
import { agent, functionTool } from "@inkeep/agents-sdk";
const calculateBMI = functionTool({
name: "calculate-bmi",
description: "Calculate BMI and health category",
inputSchema: {
type: "object",
properties: {
weight: { type: "number", description: "Weight in kilograms" },
height: { type: "number", description: "Height in meters" },
},
required: ["weight", "height"],
},
execute: async ({ weight, height }) => {
const bmi = weight / (height * height);
let category = "Normal";
if (bmi < 18.5) category = "Underweight";
else if (bmi >= 30) category = "Obese";
return { bmi: Math.round(bmi * 10) / 10, category };
},
});
const healthAgent = subAgent({
id: "health-agent",
name: "Health Assistant",
prompt: "I help with health calculations using available tools.",
canUse: () => [calculateBMI],
});
```
### Function Tool with Dependencies
Dependencies are automatically detected from your code and use the versions installed in your project:
```typescript
const fetchJoke = functionTool({
name: "fetch-joke",
description: "Fetch a random programming joke",
inputSchema: {
type: "object",
properties: {},
required: [],
},
// Dependencies detected automatically from require() calls
execute: async () => {
const axios = require("axios"); // Uses version from your project
const response = await axios.get(
"https://official-joke-api.appspot.com/jokes/programming/random"
);
return {
setup: response.data[0].setup,
punchline: response.data[0].punchline,
};
},
});
```
### Pinning Dependency Versions
If you need to pin to specific versions, specify them explicitly:
```typescript
const fetchJoke = functionTool({
name: "fetch-joke",
description: "Fetch a random programming joke",
dependencies: {
axios: "1.6.0", // Pin to exact version
},
execute: async () => {
const axios = require("axios");
// Uses axios 1.6.0 regardless of your project version
return {
joke: "Why do programmers prefer dark mode? Because light attracts bugs!",
};
},
});
```
### Built-in Node.js Modules
Function tools have access to Node.js built-in modules:
```typescript
const generatePassword = functionTool({
name: "generate-password",
description: "Generate a secure random password",
inputSchema: {
type: "object",
properties: {
length: { type: "number", default: 12, description: "Password length" },
},
},
execute: async ({ length = 12 }) => {
const crypto = require("crypto");
const charset =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*";
let password = "";
for (let i = 0; i < length; i++) {
password += charset[crypto.randomInt(0, charset.length)];
}
return { password, length };
},
});
```
## Input Schema Validation
Function tools use JSON Schema to validate input parameters. This ensures your functions receive properly typed and validated data.
### Supported JSON Schema Types
```typescript
// Example schema showing common types
{
type: "object",
properties: {
name: { type: "string", description: "User name" },
age: { type: "number", minimum: 0, description: "User age" },
active: { type: "boolean", description: "Is active" },
tags: { type: "array", items: { type: "string" } },
status: { type: "string", enum: ["pending", "approved"] }
},
required: ["name"]
}
```
## Execution Environment
Function tools run in secure, isolated sandboxes that provide a safe execution environment for your code.
### Sandbox Providers
The framework supports multiple sandbox providers:
* **Native** (default) - Uses Node.js child processes, works in most environments including cloud VMs, Docker, Kubernetes, and traditional hosting
* **Vercel** - Uses Vercel Sandbox MicroVMs for serverless environments where child process spawning is restricted (Vercel, AWS Lambda, etc.)
The sandbox provider is configured at the application level when deploying. See [Deploy to Vercel](/self-hosting/vercel#function-tools-with-vercel-sandbox) for serverless deployment configuration.
### Runtime Configuration
Configure execution settings in your application:
```typescript
import { createExecutionApp } from "@inkeep/agents-run-api";
const app = createExecutionApp({
sandboxConfig: {
provider: "native", // or 'vercel' for serverless
runtime: "node22", // Node.js 22 or 'typescript'
timeout: 30000, // 30 second timeout
vcpus: 2, // Max 2 concurrent executions
},
});
```
### Security & Isolation
Function tools execute with strong security guarantees:
* **Isolated execution** - Each function runs in its own sandbox
* **No file system access** - Cannot read or write outside the sandbox
* **Network restrictions** - Only through explicitly declared dependencies
* **Resource limits** - CPU, memory, and execution time constraints enforced
* **No state persistence** - Functions are stateless between executions
### Best Practices
* **Keep functions focused** - Each function should do one thing well
* **Minimize dependencies** - Only include packages you actually need
* **Handle errors gracefully** - Always catch and return meaningful errors
* **Test independently** - Functions should be testable in isolation
* **Document thoroughly** - Clear descriptions help agents use tools effectively
# Register MCP Servers as Tools
URL: /typescript-sdk/tools/mcp-tools
Learn how to add and configure MCP tools for your agents
***
title: Register MCP Servers as Tools
sidebarTitle: MCP Tools
description: Learn how to add and configure MCP tools for your agents
icon: "LuHammer"
----------------
MCP tools connect to external MCP servers, enabling integration with a wide ecosystem of tools and services. Registering them as tools is a two step process:
### Step 1: Get an MCP server URL
You need access to an MCP server before you can use its tools. Learn about connecting to Native servers, using Composio, using Gram, or building Custom servers in the [MCP Servers tutorial](/tutorials/mcp-servers/overview).
### Step 2: Register the MCP server as a tool in your agent
```typescript
import { subAgent, mcpTool } from "@inkeep/agents-sdk";
// Register an existing MCP server as a tool
const knowledgeBaseTool = mcpTool({
id: "knowledge-base-tool",
name: "knowledge_base",
description: "Search the company knowledge base for information",
serverUrl: "https://kb.yourcompany.com/mcp", // URL of your deployed MCP server
});
const qaAgent = subAgent({
id: "qa-agent",
name: "QA Agent",
description: "Responsible for answering questions about the company knowledge base.",
prompt: `You are a Question-Answer agent that can answer questions about the company knowledge base. You have access to the knowledge base tool to search for information.`,
canUse: () => [knowledgeBaseTool],
});
```
Tip: When adding tools to an agent, you can also reference the tool in the agent's prompt to help the agent understand how to use the tool.
## Authentication
If your MCP server requires authentication, we support various authentication methods (via credentials):
* **No Authentication** - For public APIs or internal services
* **API Key** - For services requiring API keys
* **Bearer Token** - For JWT or similar token-based authentication
* **Token Authentication** - For custom token schemes
* **OAuth Flows** - For standard OAuth 2.0 authentication
* **OAuth 2.1 Flows** - For modern OAuth 2.1 "1-click" authentication
For OAuth flows and OAuth 2.1 flows, it's recommended to use the [Visual Builder](/visual-builder/tools/mcp-servers) for easier configuration.
See [Credentials](/typescript-sdk/credentials/overview) for detailed examples and implementation guidance for each authentication type.
### Custom Headers
You can configure custom headers for your MCP server requests. Use credentials for sensitive information (API keys, tokens) and headers for non-sensitive metadata (user agent, version info, etc.).
```typescript
import { mcpTool } from "@inkeep/agents-sdk";
const customHeadersTool = mcpTool({
id: "enterprise-api",
name: "enterprise_data",
description: "Enterprise API with custom headers",
serverUrl: "https://enterprise.example.com/mcp",
headers: {
"User-Agent": "Inkeep-Agent/1.0",
"X-Client-Version": "2024.1",
},
});
```
## Selecting Tools
### Selective Tool Activation
Enable only specific tools from a server using MCP Server tool names in the `activeTools` field.
```typescript
import { mcpTool } from "@inkeep/agents-sdk";
const selectiveTool = mcpTool({
id: "limited-server",
name: "analytics_readonly",
description: "Analytics server with limited access",
serverUrl: "https://analytics.example.com/mcp",
activeTools: ["get_metrics", "generate_report"], // Only these tools
});
```
### Using `with` for Tool Selection
While `activeTools` in `mcpTool` limits which tools are available from the server, you can further refine tool access at the sub agent level using `mcpTool.with`. This allows different agents to use different subsets of tools from the same MCP server.
```typescript
import { agent, mcpTool } from "@inkeep/agents-sdk";
// Define the MCP server with all available tools
const customerSupportTool = mcpTool({
id: "customer-support-tool",
name: "Customer Support Tool",
description: "Customer Support Tool",
serverUrl: "https://customer-support.example.com/mcp",
});
// Agent that only uses specific tools from the server
const customerSupportAgent = subAgent({
id: "customer-support-agent",
name: "Customer Support Agent",
description: "Responsible for customer support",
prompt: "You are a helpful assistant",
canUse: () => [customerSupportTool.with({
selectedTools: ["customer-support-tool"],
headers: { "X-Custom-Header": "custom-value" }
})],
});
```
## Environment-Aware MCP Servers
You can also configure MCP tools to switch based on your environment. This is useful when you want to use different MCP tool configurations for development vs production.
Creating environment-aware MCP tools is a two step process:
### Step 1: Define environment configurations
```typescript title="projects/my-project/environments/development.env.ts"
import { registerEnvironmentSettings, mcpTool } from '@inkeep/agents-sdk';
import { CredentialStoreType } from '@inkeep/agents-core';
export const development = registerEnvironmentSettings({
mcpServers: {
'customer_support_tool': mcpTool({
id: 'customer-support-tool',
name: 'Customer Support Tool',
description: 'Customer Support Tool for development',
serverUrl: 'http://localhost:3000/customer-support/mcp',
})
},
});
```
```typescript title="projects/my-project/environments/production.env.ts"
import { registerEnvironmentSettings, mcpTool } from '@inkeep/agents-sdk';
import { CredentialStoreType } from '@inkeep/agents-core';
export const production = registerEnvironmentSettings({
mcpServers: {
'customer_support_tool': mcpTool({
id: 'customer-support-tool',
name: 'Customer Support Tool',
description: 'Customer Support Tool for production',
serverUrl: 'https://customer-support.example.com/mcp',
})
},
});
```
```typescript title="projects/my-project/environments/index.ts"
import { createEnvironmentSettings } from '@inkeep/agents-sdk';
import { development } from './development.env';
import { production } from './production.env';
export const envSettings = createEnvironmentSettings({
development,
production,
});
```
### Step 2: Use the MCP tool in your sub agent
```typescript title="projects/my-project/agents/customer-support-agent.ts"
import { subAgent } from "@inkeep/agents-sdk";
import { envSettings } from "../environments";
const customerSupportAgent = subAgent({
id: "customer-support-agent",
name: "Customer Support Agent",
description: "Responsible for customer support",
prompt: "You are a helpful assistant",
canUse: () => [envSettings.getEnvironmentMcp('customer_support_tool')],
});
```
This pattern is useful if you want to keep track of different credentials for different environments. When you push your project using the [Inkeep CLI](/typescript-sdk/cli-reference#inkeep-push) `inkeep push` command with the `--env` flag, the credentials will be loaded from the appropriate environment file. For example, if you run `inkeep push --env development`, the credentials will be loaded from the `environments/development.env.ts` file.
### CLI Environment Variables
The CLI respects these environment variables when using the `--env` flag:
```bash
# Set environment name via environment variable
export INKEEP_ENV=production
inkeep push # Uses production environment automatically
# Override via CLI (takes precedence)
inkeep push --env development # Uses development instead
```
# Style Components
URL: /ui-components/customization/styling
Customize the appearance of Inkeep's components.
***
title: Style Components
description: Customize the appearance of Inkeep's components.
keywords: UI styling, component customization, visual customization, theme configuration, CSS customization, design customization, UI appearance, style configuration, component theming, visual design, UI customization, component styling
icon: "LuPalette"
-----------------
The style configuration provides comprehensive settings for customizing the appearance of Inkeep widgets. This includes theming, typography, spacing, and component-specific styles.
## Theme Configuration
The theme configuration is defined through the `UserTheme` interface which extends `Partial`. This allows for deep customization of the widget's appearance.
```typescript
import { type InkeepBaseSettings } from "@inkeep/cxkit-types";
const baseSettings: InkeepBaseSettings = {
theme: {
// Basic color customization
primaryColors: {
primary: "#26D6FF",
secondary: "#6366F1",
},
// Syntax highlighter themes
syntaxHighlighter: {
lightTheme: themes.github,
darkTheme: themes.dracula,
},
// Custom styles injection
styles: [
{
key: "google-fonts",
type: "link",
value:
"https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap",
},
{
key: "custom-theme",
type: "style",
value: `
.ikp-ai-chat-message {
border-radius: 8px;
padding: 12px;
}
[data-theme='dark'] .ikp-ai-chat-message {
background: #2D3748;
}
`,
},
],
// CSS variables container class name
varsClassName: "ikp-variables",
// Disable loading the default font for the widgets
disableLoadingDefaultFont: true,
},
};
```
### Theme Properties
#### Primary Colors
The `primaryColors` property allows you to define the color variations used throughout the widget. It accepts the following color options:
```typescript
primaryColors: {
textBold?: string // Bold text color
textSubtle?: string // Subtle text color
lighter?: string // Lightest shade
light?: string // Light shade
lightSubtle?: string // Subtle light shade
medium?: string // Medium shade
mediumSubtle?: string // Subtle medium shade
strong?: string // Strong shade
stronger?: string // Stronger shade
textColorOnPrimary?: string // Text color on primary background
}
```
All colors should be provided as valid CSS color values (hex, rgb, hsl, etc). Each property is optional, allowing you to customize only the specific color variations you need.
#### Syntax Highlighter Theme
The `syntaxHighlighter` property lets you configure different themes for code blocks in light and dark modes.
By default, the Prism syntax highlighting theme we use is [oneLight](https://github.com/FormidableLabs/prism-react-renderer/blob/master/packages/prism-react-renderer/src/themes/oneLight.ts) in light mode and [vsDark](https://github.com/FormidableLabs/prism-react-renderer/blob/master/packages/prism-react-renderer/src/themes/vsDark.ts) in dark mode. To use a different theme, you can provide it in the theme.syntaxHighlighter prop.
```typescript
syntaxHighlighter: {
lightTheme: themes.github, // Theme for light mode
darkTheme: themes.dracula // Theme for dark mode
}
```
You can use published Prism themes or [create your own](https://github.com/PrismJS/prism-themes).
#### Custom Styles
The `styles` property allows injection of custom styles through two methods:
1. External Resources (type: 'link'):
```typescript
{
key: 'google-fonts',
type: 'link',
value: 'https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap'
}
```
2. Inline CSS (type: 'style'):
```typescript
{
key: 'custom-theme',
type: 'style',
value: `
.ikp-ai-chat-message {
border-radius: 8px;
padding: 12px;
}
`
}
```
Each style entry requires:
* `key`: A unique identifier to prevent duplicates and enable updates
* `type`: Either 'link' for external resources or 'style' for inline CSS
* `value`: The style content (URL for links or CSS code for styles)
#### Variables Class Name
The `varsClassName` property specifies the class name for the container that holds CSS variables:
```typescript
varsClassName: "ikp-variables"; // Default value
```
This class is added to a wrapper div that provides theming context.
## Color Mode Configuration
The color mode configuration allows you to control how the widget handles light and dark modes. This is configured through the `colorMode` property in the base settings:
```typescript
const baseSettings: InkeepBaseSettings = {
colorMode: {
// Force a specific color mode
forcedColorMode?: string,
// Enable system color mode detection
enableSystem?: boolean,
// Sync with external element
sync?: {
// Element to watch for color mode changes
target: HTMLElement | string,
// Attributes to monitor
attributes: string[],
// Function to determine dark mode
isDarkMode: (attributes: Record) => boolean,
// Optional callback for color mode changes
onChange?: (colorMode: string) => void
}
}
}
```
### Color Mode Properties
#### Forced Color Mode
Use `forcedColorMode` to explicitly set the color mode for the current page:
```typescript
colorMode: {
forcedColorMode: "dark"; // Forces dark mode
}
```
#### System Color Mode
Enable `enableSystem` to automatically switch between dark and light modes based on the user's system preferences:
```typescript
colorMode: {
enableSystem: true; // Follows system preference
}
```
#### Color Mode Sync
The `sync` property allows you to synchronize the widget's color mode with your application's theme:
```typescript
colorMode: {
sync: {
// Watch the document root for theme changes
target: document.documentElement,
// Monitor the data-theme attribute
attributes: ['data-theme'],
// Determine dark mode based on attribute value
isDarkMode: (attrs) => attrs['data-theme'] === 'dark',
// Optional: Handle color mode changes
onChange: (mode) => console.log(`Color mode changed to: ${mode}`)
}
}
```
Common sync configurations:
1. **Data Attribute Sync**:
```typescript
{
target: document.documentElement,
attributes: ['data-theme'],
isDarkMode: (attrs) => attrs['data-theme'] === 'dark'
}
```
2. **Class-based Sync**:
```typescript
{
target: document.documentElement,
attributes: ['class'],
isDarkMode: (attrs) => attrs['class']?.includes('dark-mode')
}
```
## Using CSS Variables
Inkeep provides a set of CSS variables that you can use to customize the widget's appearance. These variables are prefixed with `--ikp-` and are available within the scope of the widget.
### Basic Usage
You can use Inkeep CSS variables within your stylesheets to customize elements. For example:
```css
.ikp-chat-button__button {
background: var(--ikp-colors-inkeep-primary-medium);
}
```
### Dark Mode Styling
To apply specific styles for dark mode, use the `[data-theme='dark']` attribute selector:
```css
[data-theme="dark"] .ikp-chat-button__button {
background: #353e52;
}
```
## Customizing Icons
### AI Assistant Avatar
The AI assistant avatar can be customized through the `aiChatSettings` using the `aiAssistantAvatar` property:
it's either a string URL or an object to specify light and dark mode avatars:
```typescript
aiAssistantAvatar: {
light: string;
dark?: string;
}
```
### User Avatar
The user avatar can be customized using the `userAvatar` property in the `aiChatSettings`.
```typescript
import { type InkeepAIChatSettings } from "@inkeep/cxkit-react";
export const aiChatSettings: InkeepAIChatSettings = {
aiAssistantAvatar: "http://example.com/assistant-avatar.png",
userAvatar: "http://example.com/user-avatar.png",
// ...rest of aiChatSettings
};
```
### Custom Icons
You can customize various icons throughout the widget by providing a `customIcons` dictionary in the `baseSettings`. Each icon can be either a built-in icon or a custom SVG/image.
#### Available Icons
| Icon Name | Description |
| ------------------- | -------------------------------------------------------------------------------------------- |
| search | Search icon in search bar |
| thumbsUp | Thumbs up icon |
| thumbsDown | Thumbs down icon |
| messageCopy | Copy message icon |
| codeCopy | Copy code icon in code header |
| openLinkInNewTab | Used on hover in chat citations and search results (when `shouldOpenLinksInNewTab` is true) |
| openLinkInSameTab | Used on hover in chat citations and search results (when `shouldOpenLinksInNewTab` is false) |
| breadcrumbSeparator | Breadcrumb separator icon |
| switchToSearch | Switch to search icon |
| switchToChat | Switch to chat icon |
| chatSubmit | Chat submit icon |
| close | Close icon |
| info | Info icon next to the disclaimer and chat mode toggle |
| command | Command icon in search bar |
#### Example Configuration
```typescript
import { type InkeepBaseSettings } from "@inkeep/cxkit-react";
export const baseSettings: InkeepBaseSettings = {
customIcons: {
// Using a built-in icon
search: {
builtIn: "IoSearch",
},
// Using custom SVG/image URLs
thumbsUp: {
custom: "/path/to/thumbs-up.svg",
},
thumbsDown: {
custom: "/path/to/thumbs-down.svg",
},
messageCopy: {
custom: "/path/to/message-copy.svg",
},
codeCopy: {
custom: "/path/to/code-copy.svg",
},
openLinkInNewTab: {
custom: "path/to/open-link-in-new-tab.svg",
},
openLinkInSameTab: {
custom: "path/to/open-link-in-same-tab.svg",
},
breadcrumbSeparator: {
custom: "path/to/breadcrumb-separator.svg",
},
switchToSearch: {
custom: "/path/to/switch-to-search.svg",
},
switchToChat: {
custom: "/path/to/switch-to-chat.svg",
},
chatSubmit: {
custom: "/path/to/chat-submit.svg",
},
close: {
custom: "/path/to/close.svg",
},
info: {
custom: "/path/to/info.svg",
},
command: {
custom: "/path/to/command.svg",
},
},
// ...rest of baseSettings
};
```
> If the url for a `custom` icon is a `.svg` file it will be rendered as an `