Reconn
← Back to Blog

How we wired Trigger.dev to FastAPI automations

Reconn Team··6 min read

Reconn2’s spine is boring on purpose: one pattern per automation, whether the job is a full ConstructConnect extract or a login health probe.

Orchestration

Trigger.dev owns schedules, retries, and the operator-facing run log. Each task is a thin TypeScript wrapper that:

  1. Builds a small JSON payload (run id, optional target date, dry-run flag).
  2. POSTs to /internal/automations/ on the Render-hosted FastAPI service with X-Reconn2-Automation-Secret.
  3. Parses the JSON AutomationResult and surfaces failures as failed runs.

That keeps credentials out of Trigger payloads entirely.

Python execution

Each route delegates to a callable in reconn2.automations. The callable:

  • Validates settings (API keys, portal URLs, usernames) up front.
  • Runs the connector (OpenAI Agents sandbox, Playwright, or future paths).
  • Uploads the raw extract JSON to raw-artifacts//.json.
  • Inserts or updates public.source_runs with counts, errors, and the storage key.

Downstream graph projection reuses the same evidence model so CRM rows stay traceable.

Storage and Postgres

Supabase Storage holds bytes; Supabase Postgres holds queryable state under RLS. Signed URLs for artifacts are minted server-side — anonymous clients never see the bucket.

Failure modes we plan for

Portals change without notice. Failed ARHCA or ConstructConnect runs surface as red source_runs rows before downstream graph projection silently goes stale. ConstructConnect defaults to Playwright elastic extract; optional OpenAI sandbox and Firecrawl paths stay behind explicit feature flags.

Takeaway

Adding a connector means one FastAPI route, one Trigger task, and one row shape in source_runs. The UI, billing, and MCP layers stay stable because the contract is stable.

Read the operator runbook in docs/TRIGGER_DEV_RUNBOOK.md in the repo for task ids and manual run payloads.

Want to explore Canadian industrial data?

Start Free Trial