Connect HubSpot
Polyant ships with a suite of eight HubSpot tools — contacts, deals, tickets, tasks, notes, meetings, transactional emails, and companies — that the agent can call to read and mutate a HubSpot portal. This guide wires up a single instance against a HubSpot account: generate a Private App token, store it as an instance secret, enable the eight tools, and verify with a Playground query.
Prerequisites
- A HubSpot account where you can create a Private App (admin permission)
- A Polyant instance you can edit (the slug, e.g.
my-bot) - An authenticated admin session (or a bearer token for API calls)
Step 1: Create a HubSpot Private App token
- Open app.hubspot.com/private-apps (or, in HubSpot: Settings → Integrations → Private Apps).
- Click Create a private app.
- Under Scopes, enable at minimum:
- CRM —
crm.objects.contacts.read/write,crm.objects.deals.read/write,crm.objects.companies.read/write - Tickets —
tickets(read/write) - Tasks / Engagements —
crm.objects.tasks.read/write,crm.objects.notes.read/write,crm.objects.meetings.read/write - Transactional email (only if you intend to use
hubspotSendEmail)
- CRM —
- Save the app and copy the Access token (starts with
pat-). HubSpot only shows it once.
Step 2: Store the token as an instance secret
The token is keyed as hubspot_api_key (lowercase, snake_case — the case matters; the tools look it up with that exact key). In the admin panel: open your instance → Settings → Secrets → Add, key hubspot_api_key, value <token>, save. Via API:
curl -s -X PUT http://localhost:4000/api/instances/my-bot/secrets \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{
"secrets": [
{ "key": "hubspot_api_key", "value": "pat-eu1-..." }
]
}'Secrets are AES-256-GCM encrypted at rest.
Step 3: Enable the eight HubSpot tools
Open the instance → Tools tab → toggle on all eight:
| Tool | Purpose |
|---|---|
hubspotContact | Search, create, update contacts; supports HubSpot custom properties |
hubspotDeal | Search/create/update deals, move stages |
hubspotTicket | Ticket lifecycle with priority + open/closed filters |
hubspotCreateTask | Create a follow-up task (with due date, assignee) |
hubspotNote | Attach a note to a contact, deal, or company |
hubspotMeeting | Log a meeting against a CRM record |
hubspotSendEmail | Send a transactional email through HubSpot |
hubspotGetCompany | Look up a company by domain or ID |
All eight share the single hubspot_api_key secret — there is no per-tool token.
Step 4: Custom properties and search filters
Two extension points are worth knowing about, because they unlock most of the instance-specific behavior without changing tool code.
hubspotContact accepts a generic customProperties map (string → string) for create/update — you can write any HubSpot custom property (e.g. evento, source_campaign) without the tool knowing about it. For search it also exposes filters (HubSpot’s filter group syntax), returnProperties (which properties to project), limit, and after (pagination cursor):
curl -s -X POST http://localhost:4000/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{
"model": "my-bot",
"messages": [{
"role": "user",
"content": "Find contacts where evento equals web-summit and return name + email, max 20."
}]
}'The agent will translate that to a hubspotContact search call with filters: [{ propertyName: "evento", operator: "EQ", value: "web-summit" }], returnProperties: ["firstname", "lastname", "email"], and limit: 20.
hubspotTicket supports priority (HIGH / MEDIUM / LOW), an openOnly boolean to skip closed tickets, and a createdAfter ISO date for time-windowed queries — all useful from the prompt without writing a new tool.
Step 5: Tell the agent how to use it
The tools are now mounted, but the agent still needs to know when to call them. Update the instance prompt (Prompts tab → Tools or Persona section, depending on your layout) with a short policy, for example:
When the user asks about a contact or wants to log activity, use the
hubspot*tools. For custom HubSpot properties (e.g.evento), pass them throughcustomProperties. Never invent property names — only use ones the user explicitly mentioned or that you have already seen in the conversation.
Instance-specific property names belong in the prompt, never in tool code — the tools are deliberately property-agnostic.
Verification
- Open Playground, ask: “find contacts named Mario”.
- In the conversation trace you should see a
hubspotContacttool call withaction: "search"andcriteria.name: "Mario", followed by a tool result containing the matching contacts. - If the call returns
success: falsewith an auth error, double-check the secret key is exactlyhubspot_api_key(lowercase) and the Private App scopes cover contacts.
Caveats
- Private App tokens are long-lived but tied to the HubSpot user who created them. If that user is deactivated, the token stops working — rotate it from a service account.
- HubSpot rate-limits at 100 req / 10 s per portal on the v3 CRM API. Heavy batch operations (large imports, bulk re-syncs) should run outside the agent loop.
hubspotSendEmailrequires the transactional email add-on on the HubSpot side — without it, the tool returns a 403 from HubSpot at runtime.