HubSpot integration

HubSpot AI agents: read and update your CRM from a workflow

HubSpot's CRM API v3 is a REST API with a private app token. Give the agent a read tool for contacts and deals and, separately, write tools with approval, so lookups are cheap and changes are deliberate.

Tool type
HTTP API
Auth type
bearer_token (private app token)
Safety level
safe_read for lookups, write_sensitive for updates

What you can build

A sales assistant that pulls a contact's deals and recent notes before drafting a follow-up.

A support agent that finds the company record for a signed-in user and answers from its properties.

An operations agent that logs a call outcome or updates a deal stage after a human approves the change.

How to connect HubSpot

  1. 01Create a HubSpot private app with the scopes the agent needs (for example crm.objects.contacts.read, crm.objects.deals.read). Store the token on the tool's auth settings.
  2. 02Create an HTTP API tool for the contact search endpoint (POST /crm/v3/objects/contacts/search) with a body template that takes an email or name.
  3. 03Add write tools separately, for example PATCH /crm/v3/objects/deals/{{deal_id}}, with the safety level write_sensitive and requires approval enabled.
  4. 04Restrict allowed domains to api.hubapi.com and set widget events so end users see a status line, not raw CRM data.
  5. 05Attach the tools to the agent and confirm in the run trace that lookups run and writes wait for approval.

Example tool definition

The shape a tool takes in the AgentRow builder API. Credentials are stored on the tool's auth settings, not in its configuration, so they never reach a prompt. Placeholders in double braces are filled by the model from the input schema.

{
  "name": "hubspot_find_contact",
  "type": "http_api",
  "description": "Find a HubSpot contact by email and return its properties and associated deals. Use before drafting any follow-up.",
  "auth_type": "bearer_token",
  "safety_level": "safe_read",
  "is_readonly": true,
  "config": {
    "method": "POST",
    "url": "https://api.hubapi.com/crm/v3/objects/contacts/search",
    "headers": { "Content-Type": "application/json" },
    "body_template": {
      "filterGroups": [{ "filters": [{ "propertyName": "email", "operator": "EQ", "value": "{{email}}" }] }],
      "properties": ["firstname", "lastname", "company", "lifecyclestage"]
    },
    "allowed_domains": ["api.hubapi.com"]
  },
  "input_schema": {
    "type": "object",
    "properties": { "email": { "type": "string", "description": "The contact's email address" } },
    "required": ["email"]
  }
}

What the run trace shows

Every call appears in the run trace with the rendered request, the response status and body, timing, retries and errors, plus what the model was shown of the result. If the model never called the tool, the toolbox step shows whether it was bound for that model call and why.

Frequently asked questions

Can the agent update records without a human?

Yes, if you leave requires approval off on the write tool. Most teams keep approval on for writes and let reads run freely; the safety level and the approval flag are set per tool.

Will customer data show up in the widget?

Only what the agent puts in its answer. Tool activity shown to end users is controlled by the tool's widget events setting, and the toolbox output policy limits how much of a result the model sees.

Is there a native HubSpot connector?

A typed CRM tool type exists in AgentRow but is not executable yet, so today HubSpot is connected through HTTP API tools. Those keep working when the typed connector arrives.

Connect HubSpot to your first agent

Join the waitlist for early access. Tell us which systems you need to connect and we will point you at the right tool definitions.