Skip to content

Connect Heap to AI Agents: Automate Account and Event Ingestion

Riya Sethi Riya Sethi 10 min read AI & Agents
TrutoFor teams building AI agents

Give your AI agent Heap tools.

Connect Heap to AI agents using Truto's SDK. This guide covers bypassing Heap API quirks, binding proxy tools to LLMs, handling rate limits, and orchestrating autonomous analytics workflows.

In this guide

  1. 01Initialize the LLM
  2. 02Fetch Heap Tools
  3. 03Bind Tools to Agent
  4. 04Implement Rate Limit Backoff
  5. 05Execute the Agent Loop
Use Heap in your own ChatGPT or Claude. Elaichi, from the team behind Truto, free for 14 days. Try Elaichi

The guide

Learn how to connect Heap to AI agents using Truto's /tools endpoint. Automate event tracking, user identity resolution, and account enrichment safely.

You want to connect Heap to an AI agent so your system can autonomously map user identities, inject server-side events, enrich account properties, and process privacy deletions. Here is exactly how to do it using Truto's /tools endpoint and SDK, bypassing the need to build and maintain a custom Heap integration from scratch.

Giving a Large Language Model (LLM) read and write access to your product analytics instance is an engineering headache. You either spend weeks writing custom HTTP clients, handling unique identity schemas, and fighting rate limits, or you use a managed infrastructure layer that handles the boilerplate for you. If your team uses ChatGPT, check out our guide on connecting Heap to ChatGPT, or if you are building on Anthropic's models, read our guide on connecting Heap to Claude. For developers building custom autonomous workflows, you need a programmatic way to fetch these tools and bind them to your agent framework.

This guide breaks down exactly how to fetch AI-ready tools for Heap, bind them natively to an LLM using frameworks like LangChain, LangGraph, CrewAI, or the Vercel AI SDK, and execute complex analytics operations. For a broader look at this design pattern across multiple SaaS platforms, refer to our research on architecting AI agents and the SaaS integration bottleneck.

Why a Unified Tool Layer Matters for Agent Safety

Before writing a line of integration code, decide what layer your agent talks to. Direct API integrations - writing one custom function per raw Heap endpoint - look convenient in a prototype but push provider-specific quirks directly into the LLM's context. The model has to memorize that Heap expects flat key-value pairs for properties, that user IDs and identities have strict collision rules, and that bulk updates return plain text instead of JSON. Every one of those quirks is a hallucination waiting to happen.

A unified tool layer collapses these inconsistencies behind a stable schema. Your agent sees deterministic functions like create_a_heap_event, update_a_heap_identity_by_id, and update_a_heap_account_by_id. This approach yields concrete safety wins for production AI agents:

  1. Smaller attack surface for hallucination. The LLM only chooses from a defined set of stable function names. It never invents endpoint paths or malformed property arrays.
  2. Deterministic input validation. Every tool has a strict JSON schema. Invalid arguments (like passing both identity and user_id when only one is allowed) are rejected before they hit the Heap API.
  3. Framework agnostic execution. Tools formatted as standard JSON schemas can be passed into .bindTools() in LangChain, or mapped directly to the Vercel AI SDK, without rewriting the underlying HTTP logic.

The Engineering Reality of the Heap API

Giving an AI agent access to external systems sounds simple until you hit the engineering reality of the vendor's API. If you hardcode API requests into your agent, you will spend your sprints writing defensive integration code instead of improving your model's reasoning capabilities. Heap introduces specific challenges that break standard REST assumptions.

The 10-to-1 Identity Window Trap

Heap's identity resolution is strict. When an agent attempts to map an anonymous SDK user_id to a known identity (like an email address) using the update_a_heap_identity_by_id tool, it must navigate tight rate and relationship limits. Heap allows only one identity per user_id, and critically, at most 10 user_ids can be mapped to a single identity within a rolling one-month window. If an AI agent running a high-volume data enrichment loop blindly fires identity updates for every interaction, Heap will silently ignore the extra calls after the tenth mapping. Your agent needs a tool schema that clearly defines these parameters so it can reason about when to map identities versus when to simply attach properties to an existing record.

Non-JSON Success Acknowledgements

Standard LLMs and modern agent frameworks are trained to expect flat, intuitive JSON objects. When an agent successfully calls an API, the framework attempts to parse the response as JSON to feed it back into the context window. However, Heap's update_a_heap_account_by_id endpoint returns a plain-text OK success acknowledgment with no structured body. If you build a direct integration, your JSON parser will throw a syntax error, causing the agent to think the tool call failed. It will then retry the identical payload, creating a loop. A managed tool abstraction normalizes these responses into empty JSON objects or standard success payloads, preventing the LLM from entering a panic state.

Asynchronous State Management for Privacy Deletions

Executing GDPR or CCPA compliance deletions in Heap is not a synchronous HTTP request. When you submit users for deletion, the API responds with a deletion_request_id and a status. The agent cannot simply fire and forget; it must pause, retain the deletion_request_id in its state, and periodically poll the get_single_heap_user_deletion_by_id endpoint. Teaching an LLM to reliably manage async polling across multiple conversation turns is notoriously difficult. Exposing both the submission tool and the polling tool with explicit instructions in their descriptions is the only way to achieve reliable autonomous privacy compliance.

Core Heap AI Agent Tools

Truto provides a dynamic /tools endpoint that serves pre-configured proxy APIs formatted specifically for LLM function calling. Below are the highest-leverage tools available for Heap automation.

create_a_heap_event

This tool allows the agent to send custom server-side events to Heap. This is critical for tracking backend transactions, subscription changes, or automated AI operations that cannot be captured by client-side SDKs.

Usage Note: The agent must supply the app_id and event name. It must supply either identity (known user) or user_id (anonymous user), but never both. The tool returns an empty JSON object on success.

"A user with the identity 'sarah@example.com' just upgraded to the Enterprise tier via Stripe. Log a server-side event in Heap called 'Subscription Upgraded' and include the property 'MRR_Increase' set to 500."

update_a_heap_identity_by_id

This tool maps an anonymous session user_id to a known identity, migrating all historical session events to the permanent user profile.

Usage Note: The agent must be aware of the 10-identities-per-month limit. It requires app_id, user_id, and identity.

"We just collected an email signup from an anonymous session. Map the anonymous user_id '8374928' to the identity 'j.doe@startup.io' in Heap so we retain their past pageviews."

update_a_heap_user_by_id

This tool attaches custom key-value properties to an identified Heap user. If the identity does not exist, Heap automatically creates it as a new user.

Usage Note: Existing properties with the same name will be overwritten. It requires app_id and identity.

"Our Clearbit enrichment agent just found out that 'alex@acmecorp.com' has the job title 'VP of Engineering'. Update this user in Heap and attach the custom property 'Job_Title'."

update_a_heap_account_by_id

This tool manages B2B account properties, allowing the agent to attach or update custom fields for one or more accounts simultaneously.

Usage Note: The agent can use account_id and properties for a single update, or an accounts array for bulk updates. Truto normalizes the plain-text 'OK' response into a structured format.

"The account 'Acme Corp' just reached 50 active seats. Update their account profile in Heap to set 'Seat_Count' to 50 and 'Lifecycle_Stage' to 'Scaled'."

create_a_heap_user_deletion

This tool initiates an asynchronous data deletion request for compliance (GDPR/CCPA). It accepts up to 10,000 users per request.

Usage Note: The agent must provide an array of users, each containing a user_id or identity. It returns a deletion_request_id which the agent must save for polling.

"We received a GDPR Right to be Forgotten request for 'mark@example.com'. Submit a deletion request to Heap for this identity and let me know the deletion request ID."

get_single_heap_user_deletion_by_id

This tool polls the status of a previously submitted asynchronous deletion request.

Usage Note: The agent requires the id (the deletion_request_id). It returns the current status (e.g., pending, completed).

"Check the status of the Heap user deletion request with ID 'del_req_99834'. If it is not completed, we will check again tomorrow."

To view the complete inventory of available Heap proxy tools and their exact JSON schemas, visit the Heap integration page.

Workflows in Action

When you bind these tools to a reasoning engine, the agent can autonomously execute multi-step revenue operations and compliance workflows. Here is what that looks like in practice.

Scenario 1: Autonomous B2B Account Enrichment

When a new company signs up, the agent detects the event, enriches the account data via a third-party tool, and updates the analytics platform.

"A new user 'cto@cybernetics.io' just signed up. Log this as a 'User Signup' event. Then, update their Heap account record with the properties: 'Industry': 'Cybersecurity', 'Employee_Count': '500-1000'."

  1. The agent calls create_a_heap_event passing identity: "cto@cybernetics.io" and event: "User Signup".
  2. The agent interprets the domain to identify the account, then calls update_a_heap_account_by_id passing account_id: "cybernetics.io" with the nested properties for industry and employee count.
  3. The agent returns a confirmation to the user that the event was logged and the B2B account was enriched.

Scenario 2: GDPR Deletion Pipeline

Handling privacy requests requires exact sequencing and state tracking.

"Process a CCPA data deletion for 'david@privacy.org'. Initiate the deletion in Heap and tell me the job ID so we can track it."

  1. The agent calls create_a_heap_user_deletion passing users: [{"identity": "david@privacy.org"}].
  2. Heap processes the request asynchronously. The tool returns the response payload containing the deletion_request_id.
  3. The agent reads the response and informs the user: "Deletion initiated. The tracking ID is req_8823. You can ask me to check on this ID later."

Building Multi-Step Workflows

To build these workflows in code, you must fetch the tool definitions from Truto and bind them to your LLM. Standard frameworks like LangChain make this straightforward via .bindTools().

However, you must handle network realities. Truto does not retry, throttle, or apply backoff on rate limit errors. When the upstream Heap API returns an HTTP 429 Too Many Requests, Truto passes that error directly to the caller.

What Truto does do is normalize the upstream rate limit information into standardized HTTP headers per the IETF specification:

  • ratelimit-limit: The maximum number of requests allowed in the current window.
  • ratelimit-remaining: The number of requests remaining.
  • ratelimit-reset: The time at which the rate limit window resets.

The caller (your agent's tool execution loop) is completely responsible for reading these headers, pausing execution, and retrying. Failing to handle 429s will cause your agent to hallucinate fake success states or crash entirely.

The Architecture of a Resilient Tool Loop

Here is how data flows through a rate-limit-aware agent loop:

graph TD
    A["User Prompt<br>(Track Server Event)"] --> B["Agent Core<br>(LLM Reasoning)"]
    B --> C["Tool Call Execution<br>(create_a_heap_event)"]
    C --> D{"HTTP Status?"}
    D -->|"200 OK"| E["Return Success<br>to Agent Context"]
    D -->|"429 Rate Limit"| F["Extract Header<br>(ratelimit-reset)"]
    F --> G["Sleep / Backoff<br>(Client-Side)"]
    G --> C

Implementation with TypeScript and LangChain

Below is a production-grade example using TrutoToolManager from the truto-langchainjs-toolset SDK. This code initializes the agent, binds the Heap tools, and wraps the execution loop in a custom handler that respects the IETF rate limit headers passed through by Truto.

import { ChatOpenAI } from "@langchain/openai";
import { HumanMessage } from "@langchain/core/messages";
import { TrutoToolManager } from "truto-langchainjs-toolset";
 
// 1. Initialize the LLM
const llm = new ChatOpenAI({
  modelName: "gpt-4o",
  temperature: 0,
});
 
// 2. Fetch Heap tools via Truto for a specific integrated account
const heapTools = await TrutoToolManager.from_integrated_account(
  "<TRUTO_INTEGRATED_ACCOUNT_ID>", 
  "<TRUTO_API_KEY>"
);
 
// 3. Bind tools to the LLM
const llmWithTools = llm.bindTools(heapTools);
 
// 4. Rate-limit aware tool execution function
async function executeToolWithBackoff(toolCall: any, tools: any[], maxRetries = 3) {
  const tool = tools.find((t) => t.name === toolCall.name);
  if (!tool) throw new Error(`Tool ${toolCall.name} not found`);
 
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      // Execute the tool (makes HTTP request via Truto)
      const result = await tool.invoke(toolCall.args);
      return result;
    } catch (error: any) {
      // Check if Truto passed through an upstream 429 Rate Limit
      if (error.response && error.response.status === 429) {
        console.warn(`[Rate Limit Hit] Attempt ${attempt} of ${maxRetries}`);
        
        // Read the IETF standardized headers provided by Truto
        const resetTimeHeader = error.response.headers['ratelimit-reset'];
        
        if (resetTimeHeader && attempt < maxRetries) {
          const resetDate = new Date(resetTimeHeader).getTime();
          const now = Date.now();
          // Calculate backoff, default to 5 seconds if parsing fails
          const delayMs = Math.max((resetDate - now), 5000);
          
          console.log(`Sleeping for ${delayMs}ms before retrying...`);
          await new Promise(resolve => setTimeout(resolve, delayMs));
          continue; // Retry the loop
        }
      }
      // Rethrow if not a 429 or if we exhausted retries
      throw error;
    }
  }
}
 
// 5. Run the Agent Loop
async function runHeapAgent(prompt: string) {
  const messages = [new HumanMessage(prompt)];
  
  // First LLM pass: Model decides which tool to call
  const response = await llmWithTools.invoke(messages);
  messages.push(response);
 
  // If the model opted to call a tool
  if (response.tool_calls && response.tool_calls.length > 0) {
    for (const toolCall of response.tool_calls) {
      console.log(`Executing: ${toolCall.name}`);
      
      // Execute safely with our backoff wrapper
      const toolResult = await executeToolWithBackoff(toolCall, heapTools);
      
      // Pass the result back to the LLM context
      messages.push({
        role: "tool",
        tool_call_id: toolCall.id,
        name: toolCall.name,
        content: JSON.stringify(toolResult),
      });
    }
    
    // Final LLM pass: Model summarizes the result
    const finalResponse = await llmWithTools.invoke(messages);
    console.log("Agent:", finalResponse.content);
  } else {
    console.log("Agent:", response.content);
  }
}
 
// Execute the workflow
runHeapAgent("Log a server-side event 'API Deployed' for the identity 'dev@example.com'.");

This architecture guarantees that your agent will not crash when Heap enforces its rate limits, nor will it hallucinate a successful API call. By relying on Truto's standardized headers, you avoid writing custom header-parsing logic for every SaaS tool you integrate.

Moving from Script to System

Building an AI agent that talks to Heap is not about wrapping a single fetch request in a tool decorator. It is about state management, rate limit handling, and API schema normalization. When you hand an LLM direct access to a raw API, you inherit the provider's technical debt. By using Truto's /tools endpoint, you collapse the engineering complexity of identity maps, plain-text responses, and pagination into a uniform JSON schema that language models can actually understand.

Stop writing defensive integration code and start focusing on your model's reasoning capabilities.

Two ways to put Heap to work

Elaichifrom the team behind Truto

For you and your team

Use Heap in ChatGPT or Claude yourself

Connect Heap once, add Elaichi to ChatGPT or Claude, and ask. Every call is checked against your own permissions and logged.

Start free, 14 days No credit card required
Truto

For product teams

Give your agent Heap tools

Your customers connect their own Heap accounts. Your product gets one API and MCP tools for Heap, through Truto.

FAQ

How does Truto handle Heap API rate limits?
Truto passes upstream 429 rate limit errors directly to the caller and normalizes the rate limit data into standard IETF HTTP headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset). Truto does not automatically retry or absorb these errors, so your agent's execution loop must handle the backoff.
Can AI agents process async user deletions in Heap?
Yes. Agents can initiate the deletion using the create_a_heap_user_deletion tool, which returns a deletion_request_id. The agent must retain this ID in its state and poll the get_single_heap_user_deletion_by_id tool to verify completion.
How does the identity resolution limit work in Heap?
Heap restricts mapping an anonymous user_id to a known identity to 1 identity per user_id, and at most 10 user_ids per identity in a rolling one-month window. Truto exposes this via the update_a_heap_identity_by_id tool, but the agent must logic around these constraints.
Why use Truto instead of raw Heap API calls for LangChain?
Truto normalizes API inconsistencies, such as Heap returning plain-text 'OK' success messages instead of structured JSON, which often breaks LLM tool parsing. It provides deterministic, schema-validated tools that reduce hallucination risk.
Heap HeapAI agent tools Get a sandbox

More from our Blog