search_crm_objects
Searches and retrieves CRM records from HubSpot based on filters and criteria.
<capabilities>
- Returns a 'total' count attribute that can help perform analytical tasks on large datasets
- Useful to sample data from a specific object type to understand the data model
- Can list and filter by associations between objects (e.g., "contacts associated with company X or contacts with num_associated_deals > 1")
- Use the search_owners tool to list users/owners in the HubSpot account
</capabilities>
<returns>
List of matching CRM records containing:
- id: Unique identifier for the CRM object
- properties: Key-value pairs of property names and their values for the requested properties
- urlTemplate: URL template to view the object in HubSpot (replace {property_name} with the property value from the response)
- total: Total count of records matching the search criteria (for analytics and pagination)
- offset: Current pagination offset for retrieving the next page of results
</returns>
<usage_guidance>
- This searches for ACTUAL DATA (records), not field definitions. To discover available fields, use search_properties
- Always check 'total' count to ensure you're not missing data due to pagination limits. You MUST NOT use sample data or insufficient data as a substitute for actual data
- Use the `get_crm_objects` without properties to understand the data model of an objectType
- You can include a maximum of five filterGroups with up to 6 filters in each group, with a maximum of 18 filters in total
- [Important] CRM Analysis can be a complex task. Work with the user to refine requirements and segment large datasets into manageable parts before performing analysis
- [Important] You MUST include a clickable URL for every record returned, without exception. ALWAYS include UTM params in the URL
- [Important] You should use `associatedWith` for searching objects by associations
- [Important] When the user uses first-person language ("I", "my", "me") referring to records they own (e.g. "my deals", "money I brought in", "contacts I own"), you MUST filter by `hubspot_owner_id = {ownerId}` where ownerId comes from get_user_details.
Fetching the ownerId without applying it as a filter will return all account records, not the user's own records.
</usage_guidance>
get_properties
Fetches property definitions including data types and enumeration values.
<capabilities>
- Particularly useful for discovering valid options in enumeration-type properties
- To search for actual data, use search_crm_objects
</capabilities>
<returns>
List of property definition objects containing:
- name: Property identifier
- label: Display label
- description: Property description
- type: Data type (string, enumeration, number, etc.)
- options: For enumeration types, list of valid values with labels
</returns>
<usage_guidance>
- Property details can be unexpectedly large. Consider fetching in batches
- It's not advised to pass an objects full list of properties into this tool
</usage_guidance>
submit_feedback
Collects and submits feedback to HubSpot on dissatisfaction or user request.
<when_to_invoke>
<agent_detected_signals>
- User provides explicit correction: "No, I meant...", "Actually, I want..."
- User repeats query with different phrasing
- User states something is wrong: "That's wrong", "That's not right"
- User clarifies because agent misunderstood
- User shows dissatisfaction
</agent_detected_signals>
<user_initiated_signals>
- Explicit feedback requests: "I want to give feedback", "Let me share feedback"
- Indirect expressions to HubSpot: "HubSpot should know...", "Tell HubSpot..."
- Any clear intent to communicate feedback to HubSpot
</user_initiated_signals>
</when_to_invoke>
<agent_detected_flow>
1. Complete your response FIRST (provide the corrected answer)
2. At the END of your response, add a divider line (---) then on a NEW LINE, include ALL of these elements:
a) Acknowledge what triggered this: "I noticed [you had to correct that / you expressed frustration]"
b) Offer feedback collection: "Want to share feedback on the connector?"
c) Make it optional: "Just ask anytime — I'll send it to HubSpot."
3. If user opts in: Follow the same flow as user-initiated (steps 2-3)
4. If user declines or doesn't respond: Continue conversation normally. Never ask again this session.
</agent_detected_flow>
<user_initiated_flow>
1. Acknowledge immediately: "Happy to help with that. What would you like to share with HubSpot?"
2. If feedback is vague: "Can you be more specific about [specific aspect]? That helps HubSpot improve things."
3. Once you have clear feedback, submit the tool immediately and confirm: "Thanks. Sent to HubSpot — here's a summary of what I sent: [brief summary]. Share more anytime."
</user_initiated_flow>
<critical_requirements>
- NEVER suggest clicking Claude/ChatGPT thumbs up/down buttons sends feedback to HubSpot. Those buttons send feedback to Anthropic/OpenAI only. ONLY this tool sends feedback to HubSpot.
</critical_requirements>
search_owners
Lists and searches for owners who can be assigned to CRM records.
<capabilities>
- Supports searching by name/email or batch lookup by owner IDs
- HubSpot owner ids and user IDs are distinct, lookups only work when owner ids are provided specifically
</capabilities>
<returns>
List of owner objects containing:
- ownerId: The ID to use for hubspot_owner_id assignments
- name: Display name of the owner
- isActive: Whether the owner is currently active
</returns>
<examples>
<example>
<description>Search by name</description>
<query>{"searchQuery": "John Smith"}</query>
</example>
<example>
<description>Lookup specific IDs</description>
<query>{"ownerIds": [12345, 67890]}</query>
</example>
<example>
<description>Paginate results</description>
<query>{"limit": 50, "offset": 50}</query>
</example>
</examples>
search_properties
Finds the most relevant CRM property definitions using keyword-based search.
<capabilities>
- Lists all property definitions for specified object type when no search terms provided
- To search for actual data, use search_crm_objects
</capabilities>
<returns>
A filtered list of properties matching the search criteria containing:
- name: Property identifier
- label: Display label
- description: Property description
- matchScore: Relevance score for the property based on the search query (absent if no query is provided)
</returns>
<usage_guidance>
- Use keywords field for multiple related property guesses in a SINGLE request (recommended for performance)
- MAXIMUM OF 5 KEYWORDS ALLOWED PER REQUEST - exceeding this limit will return a validation error
- Keywords should be property name guesses, not natural language phrases
- Use query field for backward compatibility with single property guess
- No search terms provided: Returns ALL properties for the object type (useful for discovery)
</usage_guidance>
<examples>
<example>
<user_input>total number of open tickets grouped by urgency</user_input>
<thoughts>Customer is asking for total number of open tickets grouped by "urgency". I will look for the best matches on the "urgency" property for the "TICKET" object type.</thoughts>
<query>{"objectType": "TICKET", "keywords": ["urgency"]}</query>
</example>
<example>
<user_input>calls assigned to me</user_input>
<thoughts>Customer is asking us to filter by calls assigned to them. I have a few guesses for what that property might be called: "assigned_to", "assignee", "owned_by", or "owner". Let me search for those on the "CALL" object type in one efficient request.</thoughts>
<query>{"objectType": "CALL", "keywords": ["assignee", "assigned_to", "call_owner", "owned_by"]}</query>
</example>
<example>
<user_input>list each company with its name, employees amount, zip code, and when we last touched base</user_input>
<thoughts>Customer is asking us to list companies by a few attributes. I will guess keywords for each of those properties and search for them on the "COMPANY" object type in one request.</thoughts>
<query>{"objectType": "COMPANY", "keywords": ["name", "employees", "zip_code", "last_contact"]}</query>
</example>
<example>
<user_input>tickets for this year to identify top 10 most problems our customers face</user_input>
<thoughts>Customer is asking us to analyze tickets. I will return all properties for the "TICKET" object type to help with discovery.</thoughts>
<query>{"objectType": "TICKET"}</query>
</example>
</examples>
<common_mistakes>
- Do not exceed 5 keywords per request (will return validation error)
- Keywords should be property name guesses, not natural language phrases
</common_mistakes>
get_crm_objects
Fetches multiple CRM objects of the same object type in a single request.
<returns>
A list of CRM objects with their properties, identified by their unique IDs, containing:
- id: Unique identifier for the CRM object
- properties: Key-value pairs of property names and their values
- createdAt: Timestamp when the object was created
- updatedAt: Timestamp when the object was last updated
- url: URL to view the object in HubSpot
</returns>
<usage_guidance>
- Use the `search_crm_objects` tool to list a few objects first without a filter criteria
- Then use the `get_crm_objects` tool to retrieve those objects by their IDs without any properties in the tool input to understand the data model
- This will help you understand the structure of the objects and their properties
</usage_guidance>