Skip to content

[Skill Upgrade]: finance/uk_companies_house_handler — v2c deterministic role/name matchers, filing helpers, and pagination controls (parent: #220) #310

Description

@Areen-09

Skill ID

finance/uk_companies_house_handler

Current manifest version

1.2.0

Proposed change

Parent

Part of #220 (Phase v2c: Deterministic matchers, filing helpers, and pagination controls — following maintainer steering post–v2b #308 ).

Problem

Phase v2b introduced pipeline orchestration and composite actions, but left several operational gaps identified in maintainer steering and live agent runs:

  1. Zero-NLU & Lexicon Authority: The skill had remnants of string-scanning in Python code rather than letting the agent own NLU. Furthermore, Companies House defines 29 granular officer roles (cic-manager, corporate-director, llp-designated-member, manager-of-an-eeig, etc.). Without a structured taxonomy in terminology_map.yaml, agents could not cleanly filter officers by broader statutory classes without writing ad-hoc heuristics.
  2. Missing Post-Fetch Multi-Page Scanning & Search Limits: The Companies House API does not support server-side role or name filtering on /company/{company_number}/officers. A single-page fetch with a small limit cap (e.g. 10) misses matching officers located on subsequent pages (e.g. searching for "John" in Barclays PLC, which has 102 records and 18 matching Johns across multiple pages).
  3. Session Context Pollution ("Sticky Filters"): In v2b, session context retained all query parameters (officer_name, officer_role, category, latest_only). When a user asked for "John" in Turn 1, then asked for "all directors" or "Jason" in Turn 2, the old filters stuck in context and contaminated the subsequent search.
  4. Filing History Sorting & Helpers: Filing histories can contain hundreds of mixed filings. Agents querying for "latest accounts" or "latest confirmation statement" needed a deterministic, newest-first date sort and explicit helper flags (latest_only, latest_per_category) instead of fetching raw lists and parsing dates manually.
  5. Active vs. Resigned Transparency: get_officers defaults to active_only: true, but envelopes lacked explicit disclaimers, causing confusion between active counts and total historical records on file.

Proposed Changes

  • Terminology Map Lexicon — expand data/terminology_map.yaml with all 29 official Companies House officer_roles and map them into 3 canonical role_categories (directors, secretaries, corporate).
  • Pure Deterministic Officer Filtering — implement _match_officer_role using terminology_map.yaml exclusively (no regexes or fuzzy string heuristics in Python). Add case-insensitive name substring matching (officer_name / officer_filter).
  • Multi-Page Scanning & Limit Separation — scan up to 10 pages (1,000 records) in batches of 100 when filtering by name or role; default to limit: 100 for filtered searches and limit: 10 for unfiltered previews. Explicitly separate limit, items_per_page, and start_index across endpoints.
  • Deterministic Filing Helpers — sort filing history deterministically by date descending (newest first). Add latest_only: true (returns single most recent filing) and latest_per_category: true (deduplicated latest filing per category).
  • New Composite Action (resolve_company_officer) — resolve company -> halt on needs_input if ambiguous -> filter and return matching officer(s) by role and/or name substring in a single turn.
  • Context Isolation — clean persistent session context to retain only entity identity and flow, preventing volatile query filters from leaking across subsequent turns.
  • Active vs. Resigned Disclaimers — include explicit status disclaimers in terminology_note and response envelopes (active_only: bool), with clear breakdown in agent_hint.
  • Examples & Agent Loops — update examples/uk_companies_house_handler_demo.py, examples/uk_companies_house_handler_common.py, examples/gemini_uk_companies_house_handler.py, and examples/README.md to showcase deterministic officer filtering (by role and name substring), filing helpers (latest_only), clean context isolation across multi-turn dialogues, and the resolve_company_officer composite action.
  • Documentation & Manifest Sync — bump version to 1.3.0 in manifest.yaml; update instructions.md, docs/skills/uk_companies_house_handler.md, docs/skills/README.md, docs/usage/agent_loops.md, and CHANGELOG.md.
  • Unit Tests — parameterized offline unit tests covering role categories, name substring matching, multi-page collection, filing helpers, pagination offsets, context isolation, and composite actions.

Out of scope

  • Document API / PDF binary streaming and downloads (#220 Phase v2d)
  • Charges, insolvency registers, and exemptions (#220 Phase v2e)
  • Direct filing submission or write endpoints (read-only public data)

Example Input / Output Schema

Action: get_officers (Filtered by role category, including non-active)

Input Parameters:

{
  "action": "get_officers",
  "company_number": "00048839",
  "officer_role": "director",
  "active_only": false
}

Output Response Envelope

{
  "status": "ready",
  "source": "companies_house_api",
  "fetched_at": "2026-08-25T17:03:13.726131+00:00",
  "company_number": "00048839",
  "company_name": "BARCLAYS PLC",
  "total_results": 102,
  "active_count": 13,
  "matched_count": 94,
  "officers": [
   ....
  ],
  "terminology_note": "Statutory company officers in the UK comprise directors and secretaries. Includes both active and resigned officers on record.",
  "start_index": 0,
  "items_per_page": 100,
  "active_only": false,
  "context": {
    "company_number": "00048839",
    "company_name": "BARCLAYS PLC",
    "last_action": "get_officers",
  }
}

Disambiguation & Latest Filing Helper (resolve_and_get_filings -> get_filing_history)

Step A: Initial Query (resolve_and_get_filings yielding needs_input)

Input Parameters:

{
  "action": "resolve_and_get_filings",
  "query": "barclays",
  "latest_only": true
}

Output response envelope

{
  "status": "needs_input",
  "reason": "multiple_matches",
  "candidates": [
    {
      "company_number": "00048839",
      "title": "BARCLAYS PLC",
      "company_status": "active",
      "company_type": "plc",
      "address_snippet": "1 Churchill Place, London, E14 5HP",
      "date_of_creation": "1896-07-20"
    },
    {
      "company_number": "02223073",
      "title": "BARCLAYS ALDERSGATE INVESTMENTS LIMITED",
      "company_status": "active",
      "company_type": "ltd",
      "address_snippet": "1 Churchill Place, London, E14 5HP",
      "date_of_creation": "1988-02-19"
    }
  ],
  "fetched_at": "2026-08-25T17:25:47.652375+00:00",
  "agent_hint": "Ask the user which company they mean before calling further actions.",
  "next_actions": ["get_filing_history"],
  "context": {
    "company_number": null,
    "company_name": null,
    "last_action": "resolve_and_get_filings",
  },
}

Step B: Resuming with Selected company_number and latest_only: true

Input Parameters:

{
  "action": "get_filing_history",
  "company_number": "00048839",
  "latest_only": true
}

Output response envelope

{
  "status": "ready",
  "source": "companies_house_api",
  "fetched_at": "2026-08-25T17:25:56.884027+00:00",
  "company_number": "00048839",
  "total_results": 4778,
  "filing_history_status": "filing-history-available",
  "filings": [
    {
      "date": "2026-08-18",
      "category": "capital",
      "type": "SH06",
      "description": "capital-cancellation-shares",
      "description_values": {
        "date": "2026-08-03",
        "capital": [
          {
            "currency": "GBP",
            "figure": "3,375,223,808"
          }
        ]
      },
      "barcode": "AF890NP6",
      "transaction_id": "MzUzODUyNDAxNmFkaXF6a2N4",
      "document_metadata_url": "https://document-api.company-information.service.gov.uk/document/Wz8CrlfSWRKVQcPysKTJ3lbs1_fFiIiVjrNG-R-mFYs"
    }
  ],
  "start_index": 0,
  "items_per_page": 100,
  "latest_only": true,
  "latest_per_category": false,
  "context": {
    "company_number": "00048839",
    "company_name": "BARCLAYS PLC",
    "last_action": "get_filing_history",
  }
}

Acceptance criteria

  • _get_officers deterministically matches against 3 canonical categories (director, secretary, corporate), exact roles, and name substrings across multiple pages up to limit.
  • _get_filing_history sorts by date descending and supports latest_only and latest_per_category.
  • resolve_company_officer composite resolves companies and matches officers in a single turn.
  • Session context isolates persistent entity state without leaking volatile search parameters across independent turns.
  • instructions.md documents parameter hygiene, active vs. resigned disclaimers, and search limit defaults.
  • Examples in examples/ (uk_companies_house_handler_demo.py, gemini_uk_companies_house_handler.py) execute and illustrate v2c features (role/name filters, filing helpers, composite officer resolution).
  • All unit tests in skills/finance/uk_companies_house_handler/test_skill.py and repository tests in tests/ pass with mocks only.
  • Code passes flake8 and black --check . lint and formatting gates.
  • [Unreleased] entry added in CHANGELOG.md.

Implementation notes

  • Skill Bundle: skills/finance/uk_companies_house_handler/
  • Manifest: skills/finance/uk_companies_house_handler/manifest.yaml (v1.3.0)
  • Terminology Lexicon: skills/finance/uk_companies_house_handler/data/terminology_map.yaml
  • Examples:
    • examples/uk_companies_house_handler_demo.py: Offline mocked flows for role filtering, name searches, and filing helpers.
    • examples/uk_companies_house_handler_common.py: Mocked payloads for multi-page officer lists, filing history, and company profiles.
    • examples/gemini_uk_companies_house_handler.py: Interactive Gemini multi-turn agent loop for live/mocked disambiguation, role matching, and filing helpers.
    • examples/README.md: Updated usage table and descriptions for v2c.
  • Follows steering from issue #220 and PR #308.

Assignee

@Areen-09 — continuing #220 after Phase v2b #308 .

Breaking change?

No — backward compatible

Likely touch points

  • manifest.yaml version bump
  • skill.py logic
  • instructions.md
  • test_skill.py
  • docs/skills/.md and catalog row
  • examples/*.py or examples/README.md
  • data/ bundled files (address book, config templates)
  • manifest.yaml env_vars and docs/usage/api_keys.md

Metadata

Metadata

Assignees

Labels

cat: financeRegistry skill category — finance (`skills/finance/`).documentationImprovements or additions to documentation.enhancementNew feature or request.skill upgradeEnhance an existing registry skill (not a new skill).

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions