Blog
 / 
Partnerships
July 10, 2026

Track Competitor Launches in Real Time with You.com Web Search API, One, HubSpot, and Slack

Akhil Pothana

Software Engineer

Share
  1. LI Test

  2. LI Test

TLDR: Competitive intelligence workflows that rely on manual monitoring miss product launches for days or weeks. The You.com Web Search API enables AI agents to query a live, continuously updated news index programmatically, returning structured JSON results that can be filtered, enriched with CRM context from HubSpot, and routed as formatted alerts to Slack without requiring a human in the loop. This article describes a production-ready daily agent loop that does exactly that, built on withone.ai, the AI agent infrastructure platform that handles authentication, request building, and execution across all three APIs through a single CLI.

What Does This Competitive Intelligence Stack Do?

The agent loop performs four discrete steps on a daily schedule, all orchestrated through the One CLI:

  1. Search: The You.com Web Search API queries for product launch news from a defined list of competitor names. Queries use the query parameter with structured terms like "[Competitor] new product launch OR feature release", scoped to recent results using the freshness parameter (supported values: day, week, month, year).
  2. Filter: Results are scored for significance. Articles from low-signal sources (press release aggregators, content farms) are excluded. Results already seen in previous runs are deduplicated by URL hash.
  3. Enrich: The competitor name is cross-referenced against HubSpot CRM using their Search API to determine whether the competitor is an active deal, a closed-lost account, or not in the pipeline at all.
  4. Alert: A formatted Slack message is posted to #competitive-intel via the Slack Web API, including the article title, source, summary snippet, and the CRM context label (In pipeline, Closed lost, or Not in CRM).

One CLI handles OAuth authentication, request construction, and response parsing for all three platforms. This removes the need for API keys in environment variables, SDK installations, and token refresh logic.

Prerequisites: Connecting Platforms with One CLI

Before running the loop, connect You.com, HubSpot, and Slack to your One CLI account. Each connection is a one-time OAuth flow that opens in your browser:

one add you # You.com Search API
one add hubspot # HubSpot CRM
one add slack # Slack workspace

After connecting, verify all three platforms are operational:

one --agent connection list
{
 "total": 3,
 "connections": [
 {"platform": "you", "state": "operational", "key": "live::you::default::a1b2c3..."},
 {"platform": "hubspot", "state": "operational", "key": "live::hubspot::default::d4e5f6..."},
 {"platform": "slack", "state": "operational", "key": "live::slack::default::g7h8i9..."}
 ]
}

How Does the You.com Web Search API Enable This Workflow?

The You.com Web Search API returns unified search results from both web and news sources as structured JSON, without requiring HTML scraping or third-party parsing libraries. Each result object includes title, url, description, snippets (an array of text excerpts), and page_age fields, which map directly to the data an alert needs to be useful.

Finding the Right Action

One CLI follows a three-step workflow: search for the right action, read its knowledge (parameter schema), then execute. First, search for the You.com search action:

one --agent actions search you "web search" -t execute

This returns available actions with their IDs. The key action is "Search Unified Web and News Results" (GET /v1/search). Before executing, read the action's knowledge to understand the required parameters:

one --agent actions knowledge you <actionId>

Executing a Search

The search action is a GET request with query as a required query parameter and several optional filters:

one --agent actions execute you <actionId> <you_connection_key> \
 --query-params '{
 "query": "Acme Corp product launch OR new feature OR release",
 "count": 10,
 "freshness": "week",
 "livecrawl": "all"
 }'
ParameterTypeDescription
querystringRequired. The search query to execute.
countintegerNumber of results to return.
freshnessstringFilter by recency: day, week, month, year.
livecrawlstringSource selection: web, news, or all.
countrystringCountry code filter (e.g., US, GB, IN).
languagestringLanguage code filter (e.g., EN, FR, DE).
include_domainsstringComma-separated allowlist of domains to restrict results to.
exclude_domainsstringComma-separated list of domains to exclude from results.
boost_domainsstringComma-separated list of domains to boost in ranking.

The response is structured JSON with results grouped by type:

{
 "results": {
 "web": [
 {
 "url": "https://techcrunch.com/2026/06/15/acme-corp-launches-ai-suite",
 "title": "Acme Corp Launches Enterprise AI Suite",
 "description": "Acme Corp announced a new enterprise AI platform...",
 "snippets": ["The suite includes natural language processing..."],
 "page_age": "2 days ago",
 "authors": ["Jane Reporter"],
 "favicon_url": "https://techcrunch.com/favicon.ico"
 }
 ],
 "news": [
 {
 "title": "Acme Corp Announces Enterprise AI Platform",
 "description": "The new platform targets Fortune 500 customers...",
 "page_age": "2026-06-15T08:30:00Z",
 "url": "https://news.example.com/acme-ai-launch"
 }
 ]
 },
 "metadata": {
 "search_uuid": "8d7f4d8e-2f4d-4f8f-9f2d-123456789abc",
 "query": "Acme Corp product launch OR new feature OR release",
 "latency": 0.482
 }
}

For a competitive monitoring loop, you iterate over results.web and results.news, apply a significance filter (keyword matching against the description and title fields), and pass qualifying items downstream to HubSpot enrichment. Using livecrawl: "all" ensures you catch both web articles and news wire coverage in a single call.

How Do I Filter Results for Signal vs. Noise?

Raw search results for competitor names contain a high proportion of low-signal content—think listicles, job postings, analyst roundups, and republished press releases. A lightweight filter function reduces false positives before any CRM or Slack call is made.

A practical signal filter checks three conditions:

HIGH_SIGNAL_KEYWORDS = [
 "launch", "announce", "release", "new feature",
 "integrates", "partnership", "acquires", "raises"
]
NOISE_DOMAINS = ["prnewswire.com", "businesswire.com", "globenewswire.com"]

def is_high_signal(result: dict) -> bool:
 text = (result.get("title", "") + " " + result.get("description", "")).lower()
 has_signal_keyword = any(kw in text for kw in HIGH_SIGNAL_KEYWORDS)
 is_noise_source = any(nd in result.get("url", "") for nd in NOISE_DOMAINS)
 return has_signal_keyword and not is_noise_source

Deduplication across daily runs uses a persistent URL hash store (Redis or a local SQLite table). If result["url"] is already in the seen set, skip it. This prevents the same launch from triggering multiple Slack alerts across consecutive days.

How Do I Cross-Reference Competitors in HubSpot CRM?

HubSpot's CRM API allows you to search for a company by name and return its properties. This adds pipeline context to every alert—the difference between "a competitor you've never tracked" and "a competitor you lost a deal to three months ago" is operationally significant.

Finding the Right Action

one --agent actions search hubspot "search companies by object type" -t execute

This returns the "Search CRM Objects (Companies) by Object Type" action (POST /crm/objects/2026-03/{objectType}/search). Read its knowledge for the full parameter schema:

one --agent actions knowledge hubspot <actionId>

Executing a Company Search

The action requires objectType as a path variable and a JSON body with filter groups, properties, and paging parameters:

one --agent actions execute hubspot <actionId> <hubspot_connection_key> \
 --path-vars '{"objectType": "companies"}' \
 -d '{
 "after": "0",
 "filterGroups": [{
 "filters": [{
 "propertyName": "name",
 "operator": "CONTAINS_TOKEN",
 "value": "Acme Corp"
 }]
 }],
 "limit": 1,
 "properties": ["name", "lifecyclestage", "hs_lastmodifieddate"],
 "sorts": []
 }'

The response includes matching companies with their properties:

{
 "total": 1,
 "results": [
 {
 "id": "12345",
 "properties": {
 "name": "Acme Corp",
 "lifecyclestage": "opportunity",
 "hs_lastmodifieddate": "1718467200000"
 },
 "createdAt": "2024-01-10T09:00:00Z",
 "updatedAt": "2026-06-15T12:00:00Z"
 }
 ]
}

The returned lifecycle stage is appended to the Slack message payload, giving the recipient immediate orientation on competitive exposure. If total is 0, the competitor is labeled "Not in CRM".

How Do I Post Structured Alerts to Slack?

The Slack Web API chat.postMessage endpoint accepts a blocks array for rich formatting. A well-structured competitive intelligence alert includes the competitor name as the header, the article title as a link, the snippet as body text, and the CRM status as a labeled context block.

Finding the Right Action

one --agent actions search slack "post message" -t execute

This returns the "Send a Message to a Channel (chat.postMessage)" action. Read its knowledge:

one --agent actions knowledge slack <actionId>

Executing a Slack Post

The action is a POST with channel as a required body field and blocks for rich formatting:

one --agent actions execute slack <actionId> <slack_connection_key> \
 -d '{
 "channel": "#competitive-intel",
 "text": "Competitor Signal: Acme Corp — Acme Corp Launches Enterprise AI Suite",
 "blocks": [
 {
 "type": "header",
 "text": {"type": "plain_text", "text": "Competitor Signal: Acme Corp"}
 },
 {
 "type": "section",
 "text": {
 "type": "mrkdwn",
 "text": "*<https://techcrunch.com/2026/06/15/acme-corp-launches-ai-suite|Acme Corp Launches Enterprise AI Suite>*\nAcme Corp announced a new enterprise AI platform targeting Fortune 500 customers..."
 }
 },
 {
 "type": "context",
 "elements": [
 {"type": "mrkdwn", "text": "CRM Status: *In CRM — stage: opportunity*"},
 {"type": "mrkdwn", "text": "Source: techcrunch.com"}
 ]
 }
 ]
 }'

Note: Slack uses its own mrkdwn syntax, not standard Markdown. Use *bold* (single asterisks) and <url|link text> (angle brackets with pipe) instead of **bold** and [link](url).

Post to #competitive-intel once per qualifying result. Slack allows approximately 1 message per second per channel, with additional workspace-level burst limits. Rate-limit your loop to avoid burst throttling on days with multiple launches.

What Does the Full Agent Loop Look Like?

The complete daily loop combines all four steps into a single orchestrator script. Each step calls the One CLI, which handles authentication and request execution. No API keys are stored in the script itself, One CLI manages credentials through its connection system.

import json
import subprocess
import sqlite3
import os

COMPETITORS = ["Acme Corp", "Rival Inc", "Contender AI"] # replace with your list
SLACK_CHANNEL = "#competitive-intel"

# Connection keys from `one --agent connection list`, read from env vars
YOU_CONN = os.environ["YOU_CONN"]
HUBSPOT_CONN = os.environ["HUBSPOT_CONN"]
SLACK_CONN = os.environ["SLACK_CONN"]

# Action IDs from `one --agent actions search`
YOU_SEARCH_ACTION = "conn_mod_def::GK9ryAH-nnE::w01ioTnIQNe0B_qm2YtVnQ"
HUBSPOT_SEARCH_ACTION = "conn_mod_def::GJ3kQvNreBM::Zpab8Ig5TSivqCj1UhG37w"
SLACK_POST_ACTION = "conn_mod_def::GJ7H84zBlaI::BCfuA16aTaGVIax5magsLA"

def one_execute(platform, action_id, conn_key, path_vars=None, query_params=None, data=None):
 cmd = ["one", "--agent", "actions", "execute", platform, action_id, conn_key]
 if path_vars:
 cmd += ["--path-vars", json.dumps(path_vars)]
 if query_params:
 cmd += ["--query-params", json.dumps(query_params)]
 if data:
 cmd += ["-d", json.dumps(data)]
 result = subprocess.run(cmd, capture_output=True, text=True)
 if result.returncode != 0:
 raise RuntimeError(f"One CLI failed: {result.stderr}")
 return json.loads(result.stdout)

def get_seen_urls(db_path="seen_urls.db") -> set:
 conn = sqlite3.connect(db_path)
 conn.execute("CREATE TABLE IF NOT EXISTS seen (url TEXT PRIMARY KEY)")
 urls = {row[0] for row in conn.execute("SELECT url FROM seen")}
 conn.close()
 return urls

def mark_seen(url: str, db_path="seen_urls.db"):
 conn = sqlite3.connect(db_path)
 conn.execute("INSERT OR IGNORE INTO seen VALUES (?)", (url,))
 conn.commit()
 conn.close()

def get_crm_context(competitor_name: str) -> str:
 response = one_execute(
 "hubspot", HUBSPOT_SEARCH_ACTION, HUBSPOT_CONN,
 path_vars={"objectType": "companies"},
 data={
 "after": "0",
 "filterGroups": [{
 "filters": [{
 "propertyName": "name",
 "operator": "CONTAINS_TOKEN",
 "value": competitor_name
 }]
 }],
 "limit": 1,
 "properties": ["name", "lifecyclestage"],
 "sorts": []
 }
 )
 if response.get("total", 0) == 0:
 return "Not in CRM"
 company = response["results"][0]
 stage = company["properties"].get("lifecyclestage", "unknown")
 return f"In CRM — stage: {stage}"

def post_to_slack(channel: str, competitor: str, result: dict, crm_context: str):
 title = result.get("title", "Untitled")
 url = result.get("url", "")
 description = result.get("description", "")
 source = url.split("/")[2] if "/" in url else "unknown"
 one_execute(
 "slack", SLACK_POST_ACTION, SLACK_CONN,
 data={
 "channel": channel,
 "text": f"Competitor Signal: {competitor} — {title}",
 "blocks": [
 {
 "type": "header",
 "text": {"type": "plain_text", "text": f"Competitor Signal: {competitor}"}
 },
 {
 "type": "section",
 "text": {
 "type": "mrkdwn",
 "text": f"*<{url}|{title}>*\n{description}"
 }
 },
 {
 "type": "context",
 "elements": [
 {"type": "mrkdwn", "text": f"CRM Status: *{crm_context}*"},
 {"type": "mrkdwn", "text": f"Source: {source}"}
 ]
 }
 ]
 }
 )

def run_competitive_intel_loop():
 seen_urls = get_seen_urls()
 for competitor in COMPETITORS:
 response = one_execute(
 "you", YOU_SEARCH_ACTION, YOU_CONN,
 query_params={
 "query": f"{competitor} product launch OR new feature OR release",
 "count": 10,
 "freshness": "week",
 "livecrawl": "all"
 }
 )
 results = response.get("results", {})
 all_results = results.get("web", []) + results.get("news", [])
 for result in all_results:
 url = result.get("url", "")
 if url in seen_urls:
 continue
 if not is_high_signal(result):
 continue
 crm_context = get_crm_context(competitor)
 post_to_slack(SLACK_CHANNEL, competitor, result, crm_context)
 mark_seen(url)

# Schedule via cron: 0 8 * * * python run_competitive_intel_loop.py

This runs once per day, deduplicates across runs, and posts only net-new high-signal results with CRM enrichment attached. The One CLI handles all authentication transparently—if a token expires, One refreshes it automatically on the next call.

How Does This Compare to Manual Competitive Tracking?

CapabilityManual TrackingThis stack (You.com + One + HubSpot + Slack)
Detection lag1–5 daysSame day (daily cron) or near-real-time (hourly)
CRM enrichmentManual lookupAutomated via One CLI + HubSpot Companies API
Alert formatEmail forward or Slack pasteStructured Block Kit with source, snippet, CRM label
DeduplicationNone (re-alerts common)URL-hash store across runs
CoverageDepends on analyst bandwidthScales to any number of tracked competitors
Auth managementAPI keys in env vars, token refresh codeOne CLI handles OAuth for all platforms
Integration effortSDK installs + auth code per platformone add <platform> + ~80 lines of Python

Get Started

  1. Install One CLI and connect your platforms:
one init --auth browser
one add you
one add hubspot
one add slack
  1. Find your action IDs by searching each platform:
one --agent actions search you "web search" -t execute
one --agent actions search hubspot "search companies by object type" -t execute
one --agent actions search slack "post message" -t execute
  1. Copy the full orchestrator script from above, replace the connection keys and action IDs with your own (from one --agent connection list), and schedule it via cron or GitHub Actions.

The You.com Web Search API is available on a free tier with no credit card required. Full API documentation is at you.com/docs. For enterprise rate limits and SLA, contact the You.com team directly.

Built on withone.ai—AI agent infrastructure for competitive and GTM workflows.

Frequently Asked Questions

The You.com Web Search API returns unified results from both web and news sources, controlled by the livecrawl parameter (web, news, or all). Each result includes a page_age field that can be used to filter for recent content. For news-specific retrieval, set livecrawl: "news" or structure your query to include publication-intent signals (e.g., "announces", "launches", "releases") and combine with freshness: "day" or freshness: "week".

Yes. The loop is stateless aside from the seen-URL store and can be scheduled at any interval. Running it hourly on a VPS or serverless function (AWS Lambda, Google Cloud Scheduler) provides near-real-time coverage. Be mindful of You.com API rate limits and Slack's ~1 message per second per channel limit to avoid burst errors.

Store the COMPETITORS list in an environment variable, a config file, or a HubSpot list that the loop reads at runtime.  Pulling the list from HubSpot (e.g., companies tagged with a competitor label) keeps the tracked set in sync with your CRM without a code change. This assumes you've added a competitor option to the company Type property, or use a custom property—HubSpot's default Type options are Prospect, Partner, Reseller, and Vendor. You can query HubSpot for this list using the same One CLI HubSpot search action with a different filter:

one --agent actions execute hubspot <actionId> <hubspot_connection_key> \
 --path-vars '{"objectType": "companies"}' \
 -d '{
 "after": "0",
 "filterGroups": [{
 "filters": [{
 "propertyName": "type",
 "operator": "EQ",
 "value": "competitor"
 }]
 }],
 "limit": 200,
 "properties": ["name"],
 "sorts": []
 }'

The get_crm_context function should return "CRM lookup failed" on error, which is passed through to the Slack alert. The alert still posts—the CRM label is enrichment, not a blocker. One CLI returns errors as JSON with an error key, so you can check for that in the response and log persistent issues.

Yes. The withone.ai platform supports tool-calling agents that can wrap each step (You.com search, HubSpot lookup, Slack post) as a discrete tool. The orchestrator loop above maps directly to a withone.ai agent definition, with the You.com Web Search API registered as the retrieval tool and HubSpot and Slack as action tools. The One CLI's --agent flag already produces structured JSON output designed for agent consumption, so the loop can be embedded directly into an agent's tool execution layer.

Yes. Modify the COMPETITORS query template and HIGH_SIGNAL_KEYWORDS list to target different event types. For pricing changes, include terms like "pricing", "plan", "tier", "discount". For leadership, include "CEO", "CTO", "appoints", "joins". Each event type can post to a separate Slack channel by mapping competitor + event type to a channel in a routing dict.

No. One CLI handles OAuth authentication for all connected platforms. Once you run one add <platform> and complete the browser-based auth flow, One stores and refreshes tokens automatically. The orchestrator script only needs the connection keys (opaque identifiers from one --agent connection list), not raw API credentials.

    Share Article:

  1. LI Test

  2. LI Test

Related resources.

You.com + One: Automated Spend Scoring for Every Account in Your Salesforce Territory

June 15, 2026

Blog

You.com Web Intelligence Is Now Available in MindStudio’s Remy Apps

June 4, 2026

Blog

All resources.

Browse our complete collection of tools, guides, and expert insights — helping your team turn AI into ROI.

Close-up of a modern building's geometric glass facade with triangular panels reflecting purple and blue hues against a lavender border.
AI 101

Context Window: Meaning and Optimization Tips

You.com Team

May 26, 2026

Blog

API Management & Evolution

How APIs Became the Connective Tissue of LLMs

Brooke Grief

Head of Content & Web

May 20, 2026

Blog

Abstract holographic liquid metal texture with flowing iridescent waves in silver, purple, pink, and blue tones on a periwinkle background.
AI Search Infrastructure

Simple Abstractions, Dense Payloads: Tool Design for Agentic Search

Vincent Seng

Senior AI Engineer

May 18, 2026

Blog

Product Updates

Introducing the You.com Finance Research API: Agentic Research, No Infra Required

Rahul Mohan

Senior AI Engineer

May 14, 2026

Blog

Accuracy, Latency, & Cost

Same LLM, Better Web Search, Better Outcome

Chak Pothina

Product Marketing Manager, APIs

May 7, 2026

Blog

A navy graphic with the text “What Is Semi-Structured Data?” beside simple white line icons of a database cylinder and geometric shapes.
AI 101

What Is Semi Structured Data: A Developer's Guide

You.com Team

May 4, 2026

Blog

API Management & Evolution

Context Rot Is Quietly Breaking Your API Integrations

Brooke Grief

Head of Content & Web

May 1, 2026

Blog

Graphic with the text 'What Is a SERP API?' beside simple line icons of a document and circular shapes on a light blue background in minimalist style
API Management & Evolution

What Is a SERP API? Architecture, Limitations, and Why the Market Is Shifting

Brooke Grief

Head of Content & Web

April 30, 2026

Blog