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

Labels

enhancementNew feature or request.skill requestRequest for a new capability to be added to the registry.

Fields

No fields configured for Feature.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions