watsonx Orchestrate

watsonx Orchestrate

Connect with experts and peers to elevate technical expertise, solve problems and share insights.

 View Only

Building a Real-Time Competitive Intelligence Agent with IBM watsonx Orchestrate and Exa Search

By Martina Perez posted 29 days ago

  

The Problem: LLMs and Time-Sensitive Market Data

Consider this question, the kind that comes up constantly in consumer goods companies:

"How does our Taragüí Tradicional compare to Rosamonte and CBSé right now — in price and market positioning?"

Ask that to a standard LLM and you will get a well-formatted, confident answer. It will probably be wrong.

Not because the model knows nothing about yerba mate — it does. The problem is that consumer goods pricing changes week to week. A product priced at $2,900 ARS/kg three months ago may be at $3,400 today. The model has a training cutoff. It does not know what is on the shelf right now.

That is the core challenge I set out to solve: build a competitive intelligence agent for a fictional scenario based on Establecimiento Las Marías — the Argentine company behind Taragüí, Unión, and La Merced, three of the most recognized yerba mate brands in Argentina. The goal was clear: an agent that answers market questions with live data, not knowledge frozen at training time.

The solution I implemented: an agent that is explicitly prohibited from using its own knowledge about competitors, and that is required to run a web search on every single query.

The Architecture in One Paragraph

The `Agente_Competencia` (Competitive Intelligence Agent) is a native agent running on IBM watsonx Orchestrate, backed by `groq/openai-gpt-oss-120b`. It has exactly two tools — both provided via the Exa MCP server:

- `web_search_exa`: Searches the live web and returns semantically ranked, LLM-ready content
- `web_fetch_exa`: Fetches the full content of a specific URL and returns it as clean Markdown

No database. No RAG pipeline. No vector index. Just a model with strict instructions and real-time web access.

Why Exa, and Why MCP

On Exa: I evaluated several web search APIs — SerpAPI, Bing Search, Google Custom Search — and Exa stood out for one concrete reason: results come back semantically ranked and pre-processed as text, not as a list of URLs. For an LLM agent, receiving "here are the 5 most relevant excerpts about Rosamonte pricing in Argentina today" is far more useful than 10 links to fetch and parse. The `web_fetch_exa` function also converts any URL to clean Markdown — essential for extracting structured data from product pages.

On MCP: The Exa integration uses the Model Context Protocol (MCP)— an open standard that defines how AI agents discover and invoke external tools. Instead of hardcoding an Exa API client into the agent, the MCP server acts as a protocol adapter: the agent declares "I want to call `web_search_exa`", and the MCP layer handles authentication, HTTP transport, and response formatting.

In IBM watsonx Orchestrate, Exa ships as a pre-built MCP server available in the tool catalog. Connecting it to an agent requires three CLI commands from the ADK — no Python code needed for the integration:
# Register the Exa application
orchestrate connections add -a ExaLabs

# Configure for the draft environment
orchestrate connections configure -a ExaLabs --env draft -t team -k api_key

# Set the credentials
orchestrate connections set-credentials -a ExaLabs --env draft --api-key <your-api-key>
The MCP server URL is `https://mcp.exa.ai/mcp` using Streamable HTTP transport — a persistent connection that lets the agent call tools without re-authenticating on every request.

The Most Important Design Decision: Prohibit Prior Knowledge

The most critical part of this competitive intelligence agent is not its tools — it is a set of hard constraints in the system prompt that prevent the LLM from answering from its training memory.

Here is the relevant section from the agent's YAML configuration (`assets/Agente_Competencia.yaml`):

instructions: |
## Information Sources
- ALWAYS use web_search_exa and web_fetch_exa to get
up-to-date competitor information
- NEVER use the model's prior knowledge about yerba mate brands
- FORBIDDEN to invent information about competitors, prices, or product attributes
- If no web information is found, state that explicitly
- Always cite the web sources where each data point was obtained

And in the constraints block:

 ## CONSTRAINTS
1. ALWAYS run web_search_exa FIRST before mentioning any competitor
2. NEVER mention yerba mate brands not found in the current web search
3. FORBIDDEN to use the model's prior knowledge about yerba mate
4. Always cite sources: include URLs for every data point
This is the correct grounding pattern for competitive intelligence agents. You cannot rely on the LLM knowing that a competitor repositioned as premium in Q3 2024, or that a new organic product line launched last month. Making web search a mandatory first step — not an optional fallback — removes that ambiguity entirely.

The agent also has explicit instructions for when the search returns nothing:
- If web_search_exa returns no results, respond with:
"I could not find up-to-date information about [topic] in my web search.
Could you specify which brands you want to compare with Las Marías?"

Graceful degradation, not hallucination.

The Analysis Workflow

The agent's instructions define a 5-step process that fires on every competitive query:

  1. web_search_exa("best yerba mate argentina ranking 2024", numResults=5-7)
  2. web_fetch_exa(top 3 URLs → extract price, grind type, stem type, origin, aging)
  3. Build comparative table with live data + Las Marías products (same segment)
  4. Analyze positioning: premium / mid-range / budget, quality-to-price ratio
  5. Return structured output with source citations
  6. NO product recommendation — that is the orchestrator's responsibility
That last point is intentional. This agent's responsibility ends at the analysis. It does not recommend which product to buy and does not check inventory — those are separate agents. I'll explain why this separation matters in a moment.

The Output Format

The agent returns a structured Markdown response that includes a comparative table, positioning analysis, and Las Marías differentiators — all sourced from live web data:
🧉 COMPETITIVE ANALYSIS — YERBA MATE MARKET




Competitors Researched:
Based on my live web research (sources: [URLs]):
1. Rosamonte — [description from web]
2. CBSé — [description from web]
3. Cruz de Malta — [description from web]




Market Comparison:
| Brand | Price/kg | Grind | Type | Origin | Aging |
|---------------------|-----------|--------|-----------|------------|--------------|
| Taragüí Tradicional | $2,800 | Medium | With stem | Corrientes | 12-18 months |
| Rosamonte | [web] | [web] | [web] | [web] | [web] |
| CBSé | [web] | [web] | [web] | [web] | [web] |




Las Marías Positioning:
✅ [Differentiator 1 — based on real comparison with live web data]
✅ [Differentiator 2 — based on real comparison with live web data]




📊 Sources consulted:
- [URL 1]
- [URL 2]

Every cell in the competitor rows comes from a live web fetch — never from the model's weights.

My Technical Take: When to Use This Pattern

The mandatory web grounding pattern I used here is the right approach for any agent working with time-sensitive external data: pricing, news, regulatory changes, competitor moves, product availability.

The alternative — giving the LLM its own knowledge plus optional web search — is a trap. Models are overconfident. When they have a relevant-sounding answer in their weights, they will use it even if a more current answer is just one tool call away. Making web search mandatory and first removes that ambiguity entirely.

When this pattern is unnecessary: If your data is stable — your own product catalog, internal documentation, historical records — the overhead of live web fetching is not justified. Use RAG, structured lookup, or a database tool instead. In this same project, I implemented a deterministic scoring algorithm over a static catalog for the product recommendation agent — no web search needed there.

Where IBM watsonx Orchestrate specifically helps: The MCP catalog turned the Exa integration into a configuration task, not a development task. I did not write a single line of Python to connect the agent to Exa's search API. Credential management, transport layer, tool schema — all handled by the platform. For enterprise teams where operational overhead matters, this is not a small detail.

How to Deploy It

The full setup takes under 10 minutes with an IBM watsonx Orchestrate environment:
# 1. Import the agent spec
orchestrate agents import -f assets/Agente_Competencia.yaml


# 2. Register and configure the Exa connection
orchestrate connections add -a ExaLabs
orchestrate connections configure -a ExaLabs --env draft -t team -k api_key
orchestrate connections set-credentials -a ExaLabs --env draft --api-key <key>


# 3. In the Orchestrate UI: open the agent → Toolset → Add tool
# → Catalog → search "exa mcp" → select web_search_exa + web_fetch_exa

Then test it with a real competitive intelligence query:
Compare Taragüí with Rosamonte and CBSé. Which offers the best quality-to-price ratio?

The agent will search the web, fetch the relevant pages, build a live comparison table, and cite every source — without inventing a single data point.

#community-stories2
0 comments
17 views

Permalink