Skip to content

[New Skill]: finance/uk_companies_house_handler — intent-driven Companies House REST API #172

Description

@rosspeili

Skill Name

finance/uk_companies_house_handler

What should this skill do?

A deterministic Skillware bundle that lets an agent operate the Companies House REST API through structured actions—not raw HTTP in agent context.

Problem: Agents can “know” Companies House vaguely but fail on UK-specific terms (e.g. director, not CEO), company numbers vs names, multi-step flows (search → resolve → officers → filing), rate limits, and disambiguation (“BP” energy vs something else).

Solution: A skill that ships:

  1. Local API knowledge — compact, bundled reference (endpoint index, parameter shapes, UK terminology map: CEO → directors, PSC, etc.) similar to how mica_module ships a routed corpus and wallet_screening ships local indexes—not full OpenAPI dumped into every turn.

  2. Intent → operation mapping — deterministic parsers/mappers that turn structured intent (from the agent, after it read instructions.md) into one or more API operations, e.g. search_companies, get_company_profile, list_officers, list_psc, get_filing_history, fetch_document_metadata.

  3. Orchestration helpers — sequential and batch execution with clear status objects: needs_input (disambiguation), ready, partial, error. The agent owns natural-language dialogue (“Do you mean BP plc?”); the skill returns structured candidates, missing fields, and next suggested actions.

  4. Graceful failure — never guess a company number; return ranked search hits + agent_hint when ambiguous or data missing.

Non-goals for v1: Filing submissions, streaming API, or embedding an LLM inside skill.py. All NLU stays in the host agent via instructions.md; skill stays deterministic Python + requests.

Constitution themes: Use only public Companies House data; require API key via env; no caching of personal data beyond the request; always cite company number and data timestamp; not legal/accounting advice.

Auth: COMPANIES_HOUSE_API_KEY (HTTP Basic — API key as username, empty password per Developer Hub auth docs).

Example flow (agent + skill)

User: “Who is the CEO of BP?”

  1. Agent reads instructions → maps “CEO” to officers / directors (UK).
  2. Skill: resolve_company with query "BP" → search API → ranked hits → if one clear match, company_number; else status: needs_input with candidates.
  3. Skill: get_officers for company_number → current directors → structured list with names, roles, appointed dates.
  4. Optional: get_filing_document metadata if user wants downloadable filing (when available).

Phasing (maintainer alignment)

Phase Scope
v1 Search, company profile, officers, PSC, filing history list; intent mapper for common queries; local endpoint/terminology index; bundle tests (mocked HTTP)
v2+ Charges, registers, insolvency, document fetch, batch/async helpers, expanded endpoint coverage

Approve issue + v1 scope before implementation PR.

Ideal Inputs & Outputs

Design: Agent passes structured action + fields (not raw user prose into execute()). Optional user_intent string is for logging/routing hints only; mapping rules live in skill + instructions.

Input — resolve company (ambiguous name)

{
  "action": "resolve_company",
  "query": "BP",
  "jurisdiction_hint": "uk",
  "limit": 5
}

Output — needs disambiguation

{
  "status": "needs_input",
  "reason": "multiple_matches",
  "candidates": [
    {
      "company_number": "00102498",
      "title": "BP P.L.C.",
      "company_status": "active",
      "score": 0.92
    },
    {
      "company_number": "01234567",
      "title": "BP ALTERNATIVE EXAMPLE LTD",
      "company_status": "dissolved",
      "score": 0.41
    }
  ],
  "agent_hint": "Ask the user which company they mean before calling get_officers.",
  "next_actions": ["get_company_profile", "get_officers"]
}

Input — get officers (after resolution)

{
  "action": "get_officers",
  "company_number": "00102498",
  "active_only": true
}

Output — ready

{
  "status": "ready",
  "company_number": "00102498",
  "company_name": "BP P.L.C.",
  "officers": [
    {
      "name": "Example Director",
      "officer_role": "director",
      "appointed_on": "2020-03-01"
    }
  ],
  "terminology_note": "UK companies use directors, not CEOs; list includes statutory directors.",
  "source": "companies_house_api",
  "fetched_at": "2026-06-13T12:00:00Z"
}

Input — map intent (helper for agent planning)

{
  "action": "map_intent",
  "intent_keywords": ["ceo", "bp", "director"],
  "entities": { "company_query": "BP" }
}

Output

{
  "status": "ready",
  "suggested_pipeline": [
    { "action": "resolve_company", "params": { "query": "BP" } },
    { "action": "get_officers", "params": { "company_number": "<from_resolve>" } }
  ],
  "terminology_map": { "ceo": "director", "owner": "person_with_significant_control" },
  "relevant_endpoints": ["/search/companies", "/company/{number}/officers"]
}

Bundle deliverables (full skill PR, post-approval)

  • manifest.yaml, skill.py, instructions.md, card.json, test_skill.py
  • Local data/ or api_index.json + terminology_map.yaml (compact, not full OpenAPI dump)
  • docs/skills/uk_companies_house_handler.md, row in docs/skills/README.md
  • requirements: requests; env_vars: COMPANIES_HOUSE_API_KEY
  • Bundle tests mock requests (no live API in CI)

Targeted Models (if applicable)

Model Agnostic (All)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestskill requestRequest for a new capability to be added.
    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions