Skip to content

Repository files navigation

🕵️ Scout — B2B Competitive Intelligence Agent

Python Typing Lint Tests

Executive Summary: Scout is a production-grade competitive intelligence system built by PlanSmart. It turns a target company and a meeting context into a CTO-ready executive briefing: live web intelligence via Tavily, reasoning via the Anthropic Claude API, and every external integration through the Model Context Protocol (MCP).


💼 Business Case

B2B sales and strategy teams burn hours manually stitching together company research from search engines, news feeds, and internal notes. Scout automates that pipeline end to end:

  • Consistency — every briefing follows a versioned Standard Operating Procedure, not an analyst's mood.
  • Auditability — business logic lives in reviewable SKILL.md files, not buried in code.
  • Extensibility — new data sources (search, Notion, Slack) plug in as MCP servers without touching the reasoning core.

🏗️ Architecture — the WAT Framework

Scout strictly separates Workflows, Agents, and Tools. Each layer talks to the next through a typed contract, never through a concrete implementation:

graph TD
    subgraph WL["🧩 Workflows Layer — skills/"]
        SK["SKILL.md<br/><i>Executive Briefing SOP</i>"]
    end

    subgraph AL["🧠 Agents Layer — src/scout/"]
        CLI["CLI / Orchestrator<br/><i>cli.py</i>"]
        AG{"ScoutAgent<br/><i>core/agent.py</i>"}
        CFG["Pydantic Settings<br/><i>core/config.py</i>"]
    end

    subgraph TL["🔌 Tools Layer — mcp_servers/"]
        BR["MCP Client Bridge<br/><i>core/mcp_bridge.py</i>"]
        SRV["scout_intelligence_server<br/><i>FastMCP</i>"]
        TAV["Tavily Web Search<br/><i>live backend</i>"]
        STUB["Deterministic Stub<br/><i>offline backend</i>"]
    end

    LLM["Anthropic Claude<br/><i>Messages API</i>"]

    CLI --> AG
    SK -.->|"injects SOP + output contract"| AG
    CFG -.->|"validated secrets"| AG
    AG <-->|"reasoning + tool_use loop"| LLM
    AG -->|"ToolExecutor protocol"| BR
    BR <-->|"MCP over stdio"| SRV
    SRV -->|"--backend tavily"| TAV
    SRV -->|"--backend stub"| STUB

    classDef workflow fill:#eef2ff,stroke:#4f46e5,stroke-width:1px,color:#1e1b4b
    classDef agent fill:#ecfdf5,stroke:#059669,stroke-width:1px,color:#064e3b
    classDef tool fill:#fff7ed,stroke:#ea580c,stroke-width:1px,color:#7c2d12
    classDef external fill:#f1f5f9,stroke:#475569,stroke-width:1px,color:#0f172a

    class SK workflow
    class CLI,AG,CFG agent
    class BR,SRV tool
    class TAV,STUB,LLM external
Loading
Layer Directory Responsibility
Workflows skills/ Business logic as modular SKILL.md files (SOPs, output contracts). Zero prompts hardcoded in Python.
Agents src/scout/core/ The reasoning loop over the Anthropic Messages API (agent.py), driven entirely by a Skill and a typed ToolExecutor interface.
Tools mcp_servers/ External capabilities as official MCP servers (FastMCP, stdio transport). The intelligence server wraps live Tavily web search; the agent connects through an MCP client bridge (src/scout/core/mcp_bridge.py).

Key design decisions:

  • Typed seams. src/scout/core/interfaces.py defines the ToolExecutor protocol; the agent never imports a transport. Any MCP server — or a test double — plugs in behind the same contract.
  • Centralized configuration. All environment variables pass through one Pydantic Settings class (src/scout/core/config.py). No other module reads os.environ; secrets are SecretStr and never leak into logs.
  • Bounded autonomy. The tool-use loop is capped by SCOUT_MAX_TURNS; tool failures are fed back to the model as is_error results instead of crashing the run.
  • Swappable search backends. The intelligence server picks its backend via argv — --backend tavily (live) or --backend stub (deterministic, offline) — so the full MCP round trip stays testable with zero network access. Secrets travel via the child-process environment, never argv.

🚀 Quick Start

git clone <repo-url> scout-agent
cd scout-agent

python -m venv .venv
.venv\Scripts\activate        # Windows
# source .venv/bin/activate   # macOS / Linux

pip install -r requirements.txt   # locked, hash-verified dependencies
pip install -e . --no-deps
copy .env.example .env         # Windows — add ANTHROPIC_API_KEY and TAVILY_API_KEY
# cp .env.example .env         # macOS / Linux

python -m scout.cli --skill executive_briefing \
    --target "Stripe" --context "Pitching automated customer support routing"

The CLI loads the executive_briefing skill, spawns the MCP intelligence server over stdio, and prints the final markdown briefing. Select another skill with --skill <slug>.

Note: searches are live (Tavily). For a fully offline run — the mode the entire test suite uses — the server also ships a deterministic stub backend, selected with --backend stub.


🛡️ Engineering Standards (Zero-Error Discipline)

Every commit must pass all four gates — locally and in CI (Ubuntu + Windows):

Gate Command Policy
Lint ruff check . Zero findings
Format ruff format --check . Zero diffs
Types mypy . --strict, zero errors
Tests python -m pytest 100% offline — tests/conftest.py blocks all outbound HTTP; no .env required

Offline testing is enforced, not aspirational: the Anthropic client and the Tavily SDK are replaced with typed fakes, and the MCP layer is exercised by spawning the real FastMCP server as a local subprocess in stub mode — a genuine protocol round trip with zero network access.

Deterministic environments. All dependencies (runtime + dev) are locked in requirements.txt — hash-pinned and cross-platform (--universal markers cover both Ubuntu and Windows CI runners). CI installs exclusively from the lockfile with --require-hashes. To upgrade dependencies, regenerate it:

uv pip compile pyproject.toml --extra dev --universal --generate-hashes -o requirements.txt

📂 Project Structure

scout-agent/
├── src/scout/             # Agents layer (reasoning) — installed package
│   ├── cli.py             #   CLI entry point (python -m scout.cli)
│   └── core/
│       ├── agent.py       #   ScoutAgent tool-use loop
│       ├── config.py      #   Pydantic Settings (single env boundary)
│       ├── interfaces.py  #   Typed ToolExecutor protocol
│       ├── mcp_bridge.py  #   MCP stdio client bridge
│       └── skills.py      #   SKILL.md loader (Workflows layer access)
├── skills/                # Workflows layer (business logic)
│   └── executive_briefing/SKILL.md
├── mcp_servers/           # Tools layer (MCP servers)
│   └── scout_intelligence_server/
│       └── server.py      #   tavily_search tool (live Tavily / offline stub)
├── tests/                 # 100% offline test suite
├── pyproject.toml         # Packaging + tool configuration (ruff, mypy, pytest)
├── requirements.txt       # Hash-pinned dependency lockfile (uv pip compile)
└── .github/workflows/ci.yml

🧩 Extending Scout

Add a workflow: create skills/<slug>/SKILL.md with a # Skill: <Name> heading, a **Description:** line, and an SOP. It becomes selectable via --skill <slug> — no code changes.

Add a tool: implement a FastMCP server under mcp_servers/ (see mcp_servers/scout_intelligence_server/server.py for the standard), and point the CLI at it. The agent discovers its tools at runtime through MCP list_tools.


🗺️ Roadmap

  • Production web-search backend (Tavily) behind the existing MCP tool contract
  • Notion MCP integration for briefing delivery
  • Slack MCP integration for report distribution
  • Multi-skill orchestration (research → synthesis → delivery)

Built by PlanSmart — business-first automation, engineered to production standards.

About

Autonomous B2B Research & Content Engine powered by Claude Sonnet and MCP.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages