Typescript sdk

Headers

Copy page

Pass dynamic context to your Agents via HTTP headers for personalized interactions

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.

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"
  }'
Note
Note

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.

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

Tip
Tip

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:

// 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:

// 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:

// 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 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:

// 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:

// Headers
"user_id: user_123"
"user_role: admin"
"session_token: sk_live_..."

API gateway integration

Forward headers from your API gateway for consistent authentication:

// 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