import_companyresearch · git:20261020.fabe959 · 2026-10-20 · sha256 f01b2a5a4bb9cc0e
import_companyresearch git:20261020.fabe959A
Immutable. This exact content never changes and is served at /api/v1/blob/f01b2a5a4bb9cc0e.
--- name: import_companyresearch description: Import a CompanyResearch report once for a Swiss startup, or sweep pending requests into their associated dossiers without waiting for research. --- # CompanyResearch import Use `import_companyresearch(startup=None, *, uid=None, company_name=None)` from Python. The async function returns `list[CompanyResearchImportResult]`, containing the results touched by the sweep and the requested startup. This is source acquisition, not an InsightFile-producing skill. ## Workflow 1. Collect locally registered requests that the provider has already accepted. Download completed reports into their registered dossiers; leave active requests pending. Log collection errors and continue with other dossiers, returning an explicit error result. Finish collection before attempting held submissions. 2. Without `startup`, proceed to the submission sweep below. A UID or company name without a destination startup is an argument error. 3. For a startup with a completed import, return it unchanged alongside sweep results. For a registered request, reuse its identity and operation key. 4. Otherwise use the explicit `uid`, bypassing all evidence gathering and LLM calls. Without one, scan source text and available parsed sources through the shared enumeration/chunking helpers. Extract UID mentions and their context. Lookup those UIDs through CompanyResearch; only when none were found use the startup/company name, configured aliases and explicitly labelled legal names. One `generate_json` call selects a registry candidate using dossier evidence. No candidates, missing identity evidence or unresolved identity raises an error. The model cannot select a UID outside the candidate list. There is no second discovery LLM call or alternative-name research loop. 5. Persist a newly resolved dossier/UID/idempotency-key association as `on_hold`. Company lookup uses a separate endpoint and can resolve identities while research capacity is full (ordinary lookup rate limits still apply). 6. Submit held requests oldest first, using registry insertion order and `refresh=false`. Mark each `submitting` before POST and save its receipt immediately on acceptance. On HTTP 429 `concurrency_limit`, put that request back `on_hold` and stop further submissions for this invocation. Log the hold as normal progress, without waiting, repeated retries or an error result. Other errors retain their existing error/exception behavior. 7. Save an immediately available report; otherwise return without polling or waiting for research. A later invocation collects it and tries held requests. Source evidence does not call startup_profile, fetch websites/Dealum, or trigger ingestion. Unparsed binary documents become available after ordinary ingestion. Evidence and lookup budgets are in `config/import_companyresearch/settings.json`. Identity ambiguity is an error, never an automatic guess. ## Persistence and concurrency Completed imports contain `report.json` (original structured response) and `report.md` (deterministic rendering of all fields, including sources and evidence) under `<startup>/datasets/companyresearch-ch/`. No model call renders the report. The report and receipt UIDs must match the requested UID before publication. Snapshots use the shared atomic directory replacement helper. Both files identify a completed snapshot; empty/partial output does not block recovery. The registry is `cache/import_companyresearch/requests.json` in runtime storage, outside ingestible datasets. Its keys are canonical dossier slugs; records retain UID, idempotency key, request ID and status. Shared atomic writes and a filesystem lock serialize importer calls across processes on this installation. The lock is acquired in a worker thread, so it cannot block an async caller's event loop. Separate installations do not share this runtime registry; collect requests on the installation that submitted them. `on_hold` is a local queue state; `queued` means accepted by CompanyResearch. Old or interrupted `submitting` entries without a receipt remain retryable using their original keys; they are not assumed rejected after a transport failure. There is no free-slot API or hardcoded remote concurrency limit: the first capacity rejection stops that invocation's submission sweep. New startup calls can still register identities without waiting for capacity. There is no refresh option, age-based reimport, automatic resubmission after terminal provider failure, or automatic research completion monitor. Failed, cancelled and expired requests remain recorded and require operator investigation. A report-download/publication failure remains retryable through its existing receipt. The API's default cached report can be old; the provider research date remains in the output. No indexing or dataset activation occurs here. ## API and credentials Read `companyresearch_api_key` (or `COMPANYRESEARCH_API_KEY`) through `get_env_var`; never log the key. Account permissions need companies:read, research:write and reports:read. The adapter owns HTTP access, response-schema validation and structured InfrastructureError failures. HTTP 429/503 use shared transient retries and honour Retry-After, except for HTTP 429 `concurrency_limit`, which is exposed as a structured capacity error for the local queue to handle without retry delays. This retry handling is separate from research polling: research itself is never waited for. The remote API enforces account-wide job limits; rejected submissions keep their idempotency key for a later sweep. No local scheduler lease represents a five-minute remote job. `api_schema.json` contains the provider response schemas fetched from https://api.companyresearch.ch/api/openapi.json on 2026-10-20 (API 1.0.0), with references rewritten to local `$defs`. It is a boundary-validation contract, not an LLM schema. The endpoint and timeout are configuration, not skill constants. ## Usage ```bash conda run -n sictic-env python -m skills.import_companyresearch avientus conda run -n sictic-env python -m skills.import_companyresearch avientus --uid CHE-123.456.789 conda run -n sictic-env python -m skills.import_companyresearch avientus --company-name "Avientus AG" # Collect accepted requests and submit locally held requests: conda run -n sictic-env python -m skills.import_companyresearch ``` An external caller can run the sweep command every five minutes. The skill does not schedule itself or keep a polling process alive. UID above is illustrative. CLI results are JSON operational statuses and paths; errors/terminal failures produce exit code 1; pending and `on_hold` requests exit successfully. The harness accepts `/import_companyresearch [startup] [--uid UID] [--company-name NAME]`. This first implementation does not add automatic acquisition to bulk_refresh or other skills. Call the public API or CLI explicitly, and run normal dataset synchronization when the imported report is needed for retrieval.