npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@agentforge-io/connectors-hubspot

v3.0.0

Published

HubSpot connector for AgentForge — contacts, deals, and engagement tools wired to per-user OAuth2 credentials managed by the core ConnectorRegistryService.

Readme

@agentforge-io/connectors-hubspot

First-class HubSpot connector for AgentForge. Plugs into ConnectorRegistryService.register(...) from @agentforge-io/core and gives your agents seven tools that read and write contacts, deals, and engagement timelines.

import { hubspotConnector } from '@agentforge-io/connectors-hubspot';

connectorRegistry.register(
  hubspotConnector({
    clientId: process.env.HUBSPOT_OAUTH_CLIENT_ID!,
    clientSecret: process.env.HUBSPOT_OAUTH_CLIENT_SECRET!,
  }),
);

Same shape and lifecycle as @agentforge-io/connectors-google: register once at boot, the registry handles OAuth, refresh, encryption, per-user token storage, and tool materialization.


Tools

All seven tools are auto-registered the moment a user authorizes the connector in the dashboard. Each one returns a JSON-stringified payload — the model can quote individual fields.

| Tool | Use it when… | |---|---| | hubspot_search_contacts | The user mentions an email, name, phone, or company. Always call this before hubspot_create_contact. | | hubspot_get_contact | You already have a contactId and need fresh properties. | | hubspot_create_contact | Search returned nothing for the email. HubSpot 409s on duplicates — search first. | | hubspot_update_contact | Enrich an existing contact (plan tier, source, phone, custom property…). | | hubspot_create_deal | The user shows buying intent or commits to a plan. Pass contactId so the deal lands on their timeline. | | hubspot_update_deal | Move a deal stage, bump the amount, or set closedate on close. | | hubspot_log_engagement | Drop a note / call / email / meeting summary on a contact so the human rep sees what the agent did. |

Default contact return properties: email, firstname, lastname, phone, company, lifecyclestage. Override per call with the properties argument.


Setup

1. Create the HubSpot OAuth app

  1. Sign in at https://developers.hubspot.com → AppsCreate app.
  2. Under the Auth tab, set the Redirect URL to your AgentForge's connector callback (the platform exposes it at https://<your-host>/connectors/callback — the URL is the same one you configured for Google, just registered as an additional redirect).
  3. Scopes — copy the default set the connector requests:
    • oauth
    • crm.objects.contacts.read
    • crm.objects.contacts.write
    • crm.objects.deals.read
    • crm.objects.deals.write
    • crm.schemas.contacts.read
    • crm.schemas.deals.read
  4. Save → copy the Client ID and Client Secret.

If you plan to read companies, custom objects, or marketing data later, add the matching scopes here and pass them via the connector's scopes option. The default set is intentionally tight — fewer scopes mean fewer consent prompts at authorize time.

2. Drop the creds into AgentForge

In the admin dashboard → Settings → Secrets, set:

  • HUBSPOT_OAUTH_CLIENT_ID
  • HUBSPOT_OAUTH_CLIENT_SECRET

The platform's HostConnectorsModule listens for changes on those two keys and reconfigures the connector live — no server restart needed. The Directory card flips from "Needs admin setup" to "Connect".

3. End-user authorizes

Each end user clicks Connect on the HubSpot card → standard OAuth consent on HubSpot → redirect back with the authorization code → AgentForge encrypts and stores the access + refresh tokens against their userId.

Agents owned by that user (or public-chat agents whose connectorOwnerUserId points to that user) now see the seven hubspot__* tools in their picker, grouped under "HubSpot".


Typical agent loop

A common "MVP that sells" flow:

  1. Visitor opens the chat widget.
  2. Agent qualifies via conversation.
  3. hubspot_search_contacts({ query: visitor_email }) — dedupe gate.
  4. hubspot_create_contact({ email, firstname, lastname, lifecyclestage: 'lead' }) on miss; hubspot_update_contact on hit.
  5. hubspot_log_engagement({ contactId, type: 'note', body: transcript }) so the human rep has full context.
  6. When the user agrees to a plan, kick off your existing checkout flow (Stripe/LemonSqueezy), then in the webhook handler:
  7. hubspot_create_deal({ name, amount, stage: 'closedwon', contactId }).

The connector tools live alongside built-ins (current_time, fetch_url, web_search) and any other connector you've registered, so a single agent can search the web, hit HubSpot, send a Gmail confirmation, and check the clock without leaving the loop.


Custom and extra properties

Every HubSpot property (built-in or custom) is reachable via the properties map on create_contact, update_contact, create_deal, and update_deal:

// Tool call the model would make
{
  "email": "[email protected]",
  "firstname": "Alice",
  "properties": {
    "utm_source": "twitter",
    "plan_interest": "pro_annual",
    "custom_text_field": "..."
  }
}

No connector update required to support new fields — just create the property in HubSpot and let the agent fill it.


Error handling

The HTTP wrapper handles two retry classes transparently:

  • 429 Too Many Requests — honors Retry-After, up to 2 retries.
  • 5xx — single retry with ~500ms jitter.
  • 401 Unauthorized — not retried in the connector; the ConnectorRegistryService catches it, refreshes the access token, and the agent runner re-dispatches the tool call.

Anything else surfaces as a HubSpotApiError whose message includes the HTTP status and the first 500 chars of the response body. The model reads that string verbatim and will typically correct course (e.g. drop a bad property name on a 400, switch to update_contact on a 409).


Versioning

This package ships in lockstep with the rest of the @agentforge-io/* family via Changesets' fixed-group config. Bump it together with core and nest to avoid mismatched OAuth or tool-registry contracts.

See HUBSPOT_CONNECTOR_SDD.md at the repo root for the full design rationale, including the choice vs Attio/Pipedrive/Salesforce.