Knowledge & tools

HubSpot tool

The HubSpot tool gives an agent the entire HubSpot CRM through 16 generic actions parameterized by object type. Because HubSpot's data model is uniform, the same actions work across every object — contacts, companies, deals, tickets, line items, products, engagements (notes/tasks/calls/emails/meetings), quotes, and custom objects. One credential: a HubSpot Service Key.

The model: action + object_type. "Create a contact" = create_object with object_type: contacts. "Find a deal" = search_object with object_type: deals. You don't learn a separate action per object — you pick an action and the object type.

Connect HubSpot

HubSpot revamped its developer platform — private apps are now "legacy apps," and the modern credential for a data integration like this is a Service Key (no "project" needed). You must be a super admin.

  1. Settings → Integrations → Service Keys (may appear under Development → Keys → Service keys depending on account layout).
  2. Create service key, name it (e.g. "Hania").
  3. Add scopes — read and write for each CRM object you want the agent to use (see checklist).
  4. Review, Create, then copy the key immediately — it starts with pat- (region-prefixed, e.g. pat-eu1-…). Paste it into the Service Key / Access Token field. Stored encrypted, never shown again.

Scope checklist

  • Objects (read + write)crm.objects.contacts.read/.write, and the same for companies.*, deals.*, tickets.*, line_items.*, products.*.
  • Ownerscrm.objects.owners.read.
  • Schemas (properties & pipelines)crm.schemas.contacts.read, …companies.read, …deals.read.
  • Engagements (notes/tasks/calls/meetings) are generally covered by the object scopes.
Service Keys are HubSpot's modern credential — key rotation, audit logging, account-level ownership (public beta from 2026-02-10).

The object model

object_type is the kind of record: contacts, companies, deals, tickets, line_items, products, notes, tasks, calls, emails, meetings, quotes — or a custom object's objectTypeId (e.g. 2-12345).

properties (values) is not properties_to_return (names) — the single biggest source of confusion. On a write, properties is an object of field → value, e.g. {"email":"[email protected]","firstname":"Ann"}. On a read, properties_to_return is a list of field names to include in the result.

Discover before you write: list_pipelines for deal/ticket stage ids, list_owners for owner ids, list_properties for field names. Required-property gotchas: deals need pipeline + dealstage; tickets need hs_pipeline + hs_pipeline_stage; engagements need hs_timestamp (notes also hs_note_body, tasks hs_task_subject).

Field reference

  • id / id_property — the record id; or set id_property (e.g. email) to look a record up by a unique property instead.
  • properties (write) — field → value object.
  • properties_to_return (read) — which field names to return on list/get/search (HubSpot returns a default subset otherwise).
  • filter_groups / query / sorts — search filters: filter_groups is OR-of-groups, AND-of-filters-in-a-group, e.g. [{"filters":[{"propertyName":"email","operator":"EQ","value":"[email protected]"}]}]; query is free-text. Max 5 groups × 6 filters.
  • to_object_type / to_id / association_spec — for associations: the other record's type and id. Omit the spec for a default link; supply it for a labeled one.
  • inputs — for batch actions: the array of records, e.g. [{"id":"1"}] (read/archive) or [{"properties":{…}}] (create).
  • limit / after / archived — paging + archived toggle.

Actions (16)

  • Records (any object_type) — list_objects, get_object (id or id_property), create_object (properties), update_object (id, properties), delete_object (id — archives), search_objects (filter_groups/query).
  • Batchbatch_create_objects / batch_read_objects / batch_update_objects / batch_archive_objects (object_type, inputs).
  • Associations (v4)associate_objects (object_type, id, to_object_type, to_id; optional association_spec), list_associations (…, to_object_type), remove_association.
  • Lookupslist_owners (optional email), list_properties (object_type), list_pipelines (object_type).

Common recipes

  • Find or create a contact by emailget_object with id_property: email (or search_objects), else create_object.
  • Log a note on a contactcreate_object object_type notes (with hs_timestamp + hs_note_body), then associate_objects to the contact.
  • Open a deal in a pipelinelist_pipelines for stage ids → create_object object_type deals with pipeline + dealstage.
  • Create a support ticketcreate_object object_type tickets with hs_pipeline + hs_pipeline_stage.
  • Link a deal to a companyassociate_objects (deal id → company id).
  • Bulk updatebatch_update_objects with an inputs array.

Behaviors & gotchas

  • Associations: default vs labeled — a default link needs no spec; a labeled one (e.g. "Decision maker") needs association_spec.
  • Search is eventually consistent — a brand-new record may not appear in search_objects for a few seconds; fetch by id with get_object for immediacy. Search is capped (5 req/s, 10k results).
  • Custom objects work — pass the 2-XXXXX objectTypeId as object_type.

Errors & limits

HubSpot returns real HTTP status codes plus a {status, message, category, correlationId, errors[]} body (surfaced verbatim in trace/debug panels):

  • 401 — bad/expired key.
  • 403 — missing scope (the message names the object); add it to the Service Key.
  • 400 VALIDATION_ERROR — a bad or missing property (the message names it); remember deals/tickets need pipeline+stage and engagements need hs_timestamp.
  • 404 — bad id.
  • 429 — rate limit (100–190/10s; search 5/s).

Classification & lifecycle

This is a read and write tool, and it can delete (archive) records. If you run it on an autonomous bot, set its safety classification to match. It's post-call-hook eligible (runs outside the LLM turn) — e.g. create or update a CRM record after a call.