> ## Documentation Index
> Fetch the complete documentation index at: https://docs.parmanasystems.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Letting an agent update a CRM deal

> What it takes to let an AI agent move a HubSpot deal forward or change its amount, why each update needs a person, and what was proven against a real HubSpot account.

Picture a sales team in Bengaluru selling annual software plans, as an example. Their pipeline lives in HubSpot. An
agent reads the call notes after each meeting and keeps the CRM tidy: this deal moved to "contract sent", that one's
amount went from ₹4,80,000 to ₹5,20,000 after the customer added seats.

It sounds harmless. It is not. The pipeline drives the forecast, the forecast drives hiring and targets, and a deal
marked "closed won" can trigger commissions and invoices. An agent that misreads a note, or is fed a note written to
fool it, can quietly move a lost deal back to open or inflate an amount the week before the quarter closes.

## The problem: a CRM token is too much power

The usual build hands the agent a HubSpot private app token. That token can update any deal, any property, in any
direction. Whatever guardrails sit in the prompt, the token itself does not know the difference between "move forward
one stage" and "rewrite the pipeline".

## The idea: narrow the action, check the real deal, ask a person

Three things make a CRM write safe enough to hand to an agent:

1. **A narrow action.** Not "update HubSpot", but "change this deal's stage, and maybe its amount".
2. **The real state, not the agent's story.** If the agent says the deal is at "qualified to buy", ask HubSpot.
3. **A person for every write.** Someone who can be named has signed off on this deal being changed.

## How Parmana does it

The HubSpot connector has two actions: `hubspot:deal-fetch` to read a deal and `hubspot:deal-update` to change it. The
update can touch exactly two properties, `dealstage` and `amount`, in one call. A request naming any other property is
refused before any network call, not silently trimmed.

The update runs under the policy `hubspot-deal-update` 1.1.0:

* **Every update needs a signed approval** for that deal, whatever the amount. Under the older 1.0.0, small updates
  ran with no person; since 2026-09-30 none do.
* **Stages only move forward** through a fixed order, from "appointment scheduled" to "closed won", with one exception:
  "closed lost" is allowed from any stage that is not already closed. Moving backward, out of a closed stage, or to a
  stage the order does not know is refused, even with an approval.
* **The agent's facts are checked against HubSpot.** Before the policy's decision is trusted, a verifier fetches the
  real deal and re-derives the current stage, whether the move is allowed, and how much the amount changes. If the
  agent's declared facts do not match, the update is refused. If HubSpot cannot be reached, it is refused too.
* **The proposed values are bound.** The stage and amount the agent declares must equal the stage and amount in the
  request, so it cannot get approval for one change and send another.

The connector holds the token. The agent never sees it, and the token's fingerprint, never the token, is what appears
in the record. On every refusal the tests show zero calls to HubSpot.

This is the one built-in connector where Parmana reads the business system itself before deciding. For refunds,
eligibility is still the agent's word. For deals, the stage and amount facts come from HubSpot.

## What was proven, and where

The connector is tested against a mock HubSpot server in every test run, through the real `POST /execute` route. In
an earlier session it was also run live against a real HubSpot developer test account, three of three passing: a read
of a deal that does not exist reached HubSpot and came back with a real error; a refused update made no call; and a
real test deal's amount was read, nudged by 1, confirmed changed by an independent read, then put back to its exact
original value.

That live run used a locally started server and a test account, not Parmana's production deployment and not a
company's real pipeline. It ran before every update needed a signed approval, and before the live suite was rewritten
to go through the published SDK. The rewritten suite has not been run live since.

## What it does not do

* **The approval covers the deal, not the new values.** A person approves changing this deal; the approval does not fix
  which stage or what amount. The stage rules and the HubSpot check still apply, but within them the approver is
  trusting the agent's numbers for that one use.
* **Only deals, only stage and amount.** No contacts, companies, deletes, other properties or webhooks.
* **One stage order for everyone.** Per-pipeline stage orders are not wired up.
* **No real company pipeline is connected.** The only live run was a test account.
* **Reads need approval too.** Even fetching a deal needs a signed approval for that deal, which makes reading slower
  than most teams expect. That is deliberate, and its own essay.
* **One person approves.** In Parmana's own production one approver is trusted, and I hold that key.
* **It does not stop a direct call.** An agent that keeps its own HubSpot token can call HubSpot without Parmana.

## The takeaway

A CRM is a record of what the business believes about its customers. Letting an agent write to it is reasonable when
the action is narrow, the facts come from the CRM rather than the agent, and a person signs each change. The part still
missing is the one that matters most to a buyer: a run against a real team's pipeline.

**Read more:** [HubSpot](/integrations/hubspot), [Human approval](/concepts/human-approval),
[Credential isolation](/concepts/credential-isolation).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.