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.
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.
- Settings → Integrations → Service Keys (may appear under Development → Keys → Service keys depending on account layout).
- Create service key, name it (e.g. "Hania").
- Add scopes — read and write for each CRM object you want the agent to use (see checklist).
- 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 forcompanies.*,deals.*,tickets.*,line_items.*,products.*. - Owners —
crm.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.
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_groupsis OR-of-groups, AND-of-filters-in-a-group, e.g.[{"filters":[{"propertyName":"email","operator":"EQ","value":"[email protected]"}]}];queryis 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). - Batch —
batch_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. - Lookups —
list_owners(optional email),list_properties(object_type),list_pipelines(object_type).
Common recipes
- Find or create a contact by email —
get_objectwithid_property: email(orsearch_objects), elsecreate_object. - Log a note on a contact —
create_objectobject_typenotes(withhs_timestamp+hs_note_body), thenassociate_objectsto the contact. - Open a deal in a pipeline —
list_pipelinesfor stage ids →create_objectobject_typedealswithpipeline+dealstage. - Create a support ticket —
create_objectobject_typeticketswithhs_pipeline+hs_pipeline_stage. - Link a deal to a company —
associate_objects(deal id → company id). - Bulk update —
batch_update_objectswith aninputsarray.
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_objectsfor a few seconds; fetch by id withget_objectfor immediacy. Search is capped (5 req/s, 10k results). - Custom objects work — pass the
2-XXXXXobjectTypeId asobject_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.