Attended Power Automate pipeline that drafted several hundred Maine annual reports per filing season for a law firm’s 1,000+ entity registered-agent book. Built early 2025. Anonymized.
Problem. Recurring annual-report drafting across many entity-type variants, no submission API, high-liability review boundary.
Stack. Power Automate cloud flows, Power Automate Desktop (attended), Excel Online registry, Word mail merge, Outlook, iManage (GUI only).
Role. Designed and built the registry, type routing, attended desktop workers, exception handling, logging, mail-merge handoff, and a separate GUI automation that filed completed packages into the DMS.
Constraint. Drafts and stages packages for attorney/client review. Does not auto-submit legal attestations.
Outcome (one season). Predrafting finished across two overnight attended runs. Clean cases needed about a minute of wizard work to save the SoS draft and capture details; ~90% of drafts needed no edit. Filing a correct draft was trivial. Maintenance would have been low, but the portal path stayed brittle.
This writeup describes work I designed and built professionally. No client information, proprietary code, credentials, selectors, or employer-specific configuration. Patterns are concrete enough to be credible and abstract enough to keep confidentiality intact.
Registered-agent annual reports: each entity must file, deadlines stagger, data mostly repeats year to year, and each filing still requires:
- Log into the secretary of state portal
- Look up the entity
- Walk a multi-step contact wizard
- Confirm or update directors, officers, registered agent, principal office
- Save for attorney review (the firm does not auto-submit)
- Trigger downstream client communications: notices, invoices, cover letters, and sometimes corporate minutes
Manual work: 5–10 minutes per entity. Several hundred drafts concentrated in spring means hundreds of paralegal hours, high error rates, thin audit trail.
Before automation, filings lived in a sprawl of Excel files and Word tables, siloed by registered agent. No shared schema, no validation, no CRM. Building automation meant building the registry first.
Internal stack. Microsoft 365 Business Standard, on-prem iManage, Outlook. I had a Power Automate Premium license (which unlocked Desktop). No third-party RPA, no paid API services, no external databases inside the project’s runway.
iManage via GUI only. APIs existed, but the support vendor required a certified developer for integration work the firm would not retain for this project. Document handoff stayed attended UI automation.
No unattended license. The flow ran attended on my workstation. I was the only operator. Extra seats or “robot” licenses meant procurement delays; workarounds like email-triggered remote kicks would have been janky and slow to approve. Throughput target: what can finish during overnight attended sessions and normal workday time, as small resumable units—not one long-running job.
External: InforME has roster export, not filing API. Maine’s portal can export CSV/TSV of entities for a given registered agent (charter number, status, appointment date)—useful for registry sync. Submission has no POST, XML, or CSV batch path. Digital filing is the web wizard; the alternative is paper plus check. Browser automation against the wizard was the only digital path.
Excel Online as registry is constraint-driven. I would not design a system of record around a workbook from scratch, but it was the option inside the license envelope with native Power Automate connectors and first-class Word mail merge. (See “What I’d do differently.”)
Legacy government wizard. Server-side HTML tables that vary by entity type. Conditional fields. Fragile session state. Rate limits on unauthenticated paths, timeouts mid-flow, quiet UI changes between seasons.
Eight entity-type variants. Domestic/Foreign Business Corporation, Domestic/Foreign LLC, Domestic/Foreign Nonprofit, Limited Partnership, Limited Liability Partnership, plus rarer types. Different wizard paths, required fields, and validation. Nonprofits do not carry forward their brief statement of business character from the prior year—every other type does. That broke early builds; I first treated it as one or two bad entities, then confirmed it for all nonprofits and no other type. The nonprofit worker refetches and repopulates that field every year.
First-year entities are nearly empty. Maine formation does not require officer, director, or principal-office data. New entities arrive with a name, charter number, and a filing obligation. “Fill from scratch” is a distinct path, not a degenerate confirm-or-update.
Confirmation PDFs are not a reliable source of truth. Filings come from a Tyler Technologies platform that emits Oracle-reported native PDFs. They look right; native text extraction loses layout. Columns drift, multi-row entries collapse, structure shifts with officer/director counts. OCR adds a probabilistic step that is hard to defend for legal records. Live HTML from the wizard is the deterministic extract path.
Liability needs humans twice. Annual reports include registered-agent acceptance and officer confirmations. The flow drafts and saves; attorney reviews with client-facing docs; client reviews; adjustments return; attorney submits. Success is “draft and package staged,” not “filing complete.”
Downstream is half the value. Finished drafts trigger mail merge: client notice, invoice, cover letter, and (when bylaws require it) corporate minutes.
A scheduled Power Automate cloud flow orchestrates and queues. A main desktop flow routes each entity into one of about eight entity-type subflows that drive the browser. Cloud can schedule; PAD stays attended, so the cloud side queues and the desktop side drains during overnight and workday sessions. The registry is Excel Online. Run progress and per-entity errors append to plain-text logs written from the flow.
┌─────────────────────────────────────────────────────────────┐
│ ENTITY REGISTRY │
│ Excel Online: entity book │
│ fields: name, state ID, type, due date, last filed, │
│ officers, registered agent, status │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ CLOUD ORCHESTRATOR (server-side) │
│ Scheduled cloud flow: queues entities due in 30d window, │
│ hands work to the attended desktop session, logs runs │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ MAIN PAD FLOW → ~8 ENTITY-TYPE SUBFLOWS │
│ Router dispatches by type; each subflow owns its wizard │
│ path (shared steps were duplicated across subflows) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ BROWSER AUTOMATION (attended-only) │
│ Power Automate Desktop: │
│ - Navigate to InforME │
│ - Look up entity │
│ - Walk wizard (entity-type-specific path) │
│ - Extract current values from rendered HTML tables │
│ - Compare to registry; flag deltas │
│ - Populate updates │
│ - Save draft (do NOT submit) │
│ - Capture screenshots at key checkpoints │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ ERROR HANDLING (append + continue) │
│ - Missing field (regex match "is missing") → log + skip │
│ - Generic portal error → log + retry past │
│ - Session timeout (rare) → re-login + resume │
│ - Already-filed / ineligible status → log + skip │
│ - Unknown wizard state → halt + alert │
│ Counter written to log → early exit is resumable │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ DOWNSTREAM MAIL MERGE │
│ - Client notice, invoice, cover letter │
│ - Conditionally corporate minutes │
│ - Stage for attorney + client review │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ REVIEW → FILE → DMS │
│ Attorney + client review; adjustments fed back │
│ Attorney submits correct draft on the portal │
│ Separate PAD flow uploads the package into iManage (GUI) │
│ Registry marked complete → last-filed date updated │
└─────────────────────────────────────────────────────────────┘
Predrafting for the season completed across two overnight attended runs. Partnerships were uncommon; their edge cases were under-tested and hit a bug mid-run. Failure was an early exit. Because the counter wrote to the log, the run resumed cleanly from the last processed entity.
SQLite via PAD’s Python 3 action. Technically reachable (SQLite is in the stdlib). Ruled out for this project’s scope: a local file is invisible to cloud orchestration without a custom connector I wasn’t building; workstation persistence is a single point of failure; no sanctioned cloud sync for a binary the DMS didn’t already manage. I did later import captured draft details into SQLite with Python—useful, but out of scope for the filing-season build.
Microsoft Access. SQL semantics without real concurrency; Excel fragility without Excel’s compatibility; same single-file-on-a-workstation problem.
Excel Online. What shipped. Weaker on schema, validation, and concurrency. Wins on the constraints that mattered: Power Automate connectors, cloud persistence/versioning, multi-user access, and Word mail merge. Fee schedule and per-client filing data lived in the same workbook, so cover letters, invoices, authorization forms, and the draft package collated in one mail-merge pass.
A single flow with nested conditionals for every entity type became unmaintainable within two weeks. A main flow routes into roughly eight entity-type subflows. Each subflow is shorter and independently testable. The cost is duplication: login, lookup, save, and screenshots were repeated. A bug fix in one often needed the same edit in the others. Child flows would have been the right next refactor; I didn’t extract them in this season.
Registry data goes stale. The flow extracts current values from the wizard’s HTML, compares to the registry, and flags deltas before drafting. PDF extraction looked simpler on day one and failed the layout-stability test. Extraction caught hundreds of stale registry records and turned the job into a data-quality pass, not only a filing pass.
The flow stops at “save draft.” Submission is a legal attestation. The package then moves attorney → client → adjustments → attorney submit. Metrics reflect “draft and package staged,” not “filing complete.”
The portal changes quietly. Screenshots at login, entity found, wizard step N, extraction complete, and draft saved cut diagnosis from days to hours when something breaks at scale.
Dominant InforME error on the authenticated path: a generic “sorry, something went wrong with your transaction” page that usually doesn’t kill the session and can be retried past. Response for most failures: append entity, failure type, and matched text to a plain-text log; advance the counter; continue. Session expiry → re-login and resume. Missing field / ineligible / already filed → log and skip. Unknown wizard state → halt. No single entity failure halts the batch. The log is the post-run work queue; the counter makes early exits resumable.
Cover letter (by registered-agent attorney), invoice (fee schedule in the same workbook), credit-card authorization when needed, corporate minutes when bylaws require them. One orchestrated package beats five separate tickets.
The laptop docked to external monitors at the office and ran undocked elsewhere. PAD falls back to coordinates when selectors are ambiguous; InforME had several such spots. Every dock/undock, monitor swap, or display-scaling change shifted the click space. Misclicks were common until I pinned a known-good display config, anchored to find-image-then-offset where possible, and halted workers when resolution didn’t match the recorded config.
In hindsight, a dummy HDMI/DP dongle for a fixed virtual desktop—or a dedicated desktop—would have been cleaner. I experimented with blocking physical I/O as a pseudo-unattended workaround; that was likely outside permitted license use and not something security would accept.
Rare formations, suite numbers the wizard parses wrong, optional-but-conditionally-required fields I couldn’t reproduce reliably: flag and hand back to the GUI rather than automate every quirk. ~90% of drafts were correct as saved. Periodic client changes were edited manually. Automating the common path and finishing the tail by hand (or paper in a few cases) kept one-person maintenance viable.
Pattern: append to a plain-text log and continue. Halt only when the flow cannot safely proceed.
| Failure mode | Portal signal | Flow response |
|---|---|---|
| Already filed for the year | Red text on charter entry with filed date | Log, skip, advance |
| Status not eligible | “Not eligible…,” dissolved / cancelled / suspended | Log reason, skip, advance |
| Saved draft / resume | Counter in text log; registry filed flags | Resume from last processed entity |
| Required field missing | Regex "is missing" on page text |
Log field; skip or halt by field |
| Generic transaction error | “Sorry, something went wrong…” without killing session | Log, retry on next attempt |
| Session timeout (rare) | Redirect to login / expired page | Re-auth, resume |
| Display / coordinate mismatch | Pre-run resolution check fails | Halt before clicks; fix display |
| Under-tested type edge case (e.g. Partnerships) | Wizard path diverges | Early exit; resume via log counter |
| Unknown wizard state | Selector and image fallback both fail | Halt, log context, escalate |
DocuSign for corporate minutes. Technically easy (API + Power Automate plugin). Killed by per-envelope cost at volume and procurement/IT cycles that didn’t fit the runway. Signed minutes stayed on the existing manual workflow.
Microsoft Forms for client confirmation. Prefill at scale was awkward; forms didn’t look like firm correspondence (phishing risk for older clients); returned data would drift against registry and portal. Client confirmation stayed in email and letter.
AffiniPay / ClientPay QR codes on invoices. Custom per-invoice links with IOLTA vs operating routing were effectively free on the existing processor. Attorneys disliked QR codes for older clients; finance did not want lower-friction card pay because processing fees hit margin. Short-link-only fixed the QR concern, not the fee concern. Shelved.
Firm book size and revenue stay undisclosed. From one filing season:
- Predraft throughput: season predraft completed across two overnight attended runs (with a resumable Partnerships early-exit mid-way).
- Clean-case predraft: ~1 minute to walk the wizard, save the SoS draft, and capture details.
- Draft quality: ~90% needed no edit; remaining edits were manual as client changes arrived.
- Filing: once the draft was correct, submission was trivial; a separate attended flow uploaded packages into iManage via GUI.
- Coverage: common entity types in the Maine registered-agent book, one coordinated pipeline.
- Durability: process was strong enough to ship the season and brittle enough that portal or display drift remained a live risk.
Shared child flows. Pull login, lookup, draft save, and screenshots out of the duplicated subflows so a fix lands once.
Dedicated display. Fixed desktop or dummy display dongle; stop carrying dock/undock coordinate risk on a laptop.
DOM / page-state audit log. Capture and filter DOM snapshots at failure points so unknown wizard states become a mapped state machine, not a halt-and-guess. Natural next step after plain-text error logs.
Bounded retries instead of fixed waits. Poll until a known page state, then proceed. Reserve hard halts for genuinely unknown states.
Richer regression without a full portal mock. Known-good entity suite plus saved HTML snapshots of wizard steps for offline selector checks.
Registry: keep Excel Online as the mail-merge view; move system-of-record history and audit to Dataverse or SQL when licensing allows. Not Access.
End-to-end orchestrator. Fold notice assembly, payment tracking, and finance handoff into the same queue so those steps stop being manual leftovers.
Stronger RPA runtime if licensing allows. UiPath-class selectors and orchestrator fit sustained portal work better than PAD. The realistic choice in early 2025 was PAD or nothing.
Maine only. Other states could reuse the pattern; this book didn’t have the volume to justify building and edge-testing them.
- Microsoft Power Automate (cloud + desktop, attended only)
- Excel Online (entity registry)
- Plain text files (run logs, failure records, resume counter)
- Microsoft Word (mail merge)
- Microsoft Outlook
- iManage (on-prem DMS, GUI upload automation)
I am not publishing exported Power Automate Desktop (.robin) files. The patterns and lessons above are portable; the implementation artifacts are work product that belong with the firm. No selectors, portal URLs, credentials, templates, fee schedules, or client-identifying data.
Happy to walk structure at a whiteboard in an interview. The design choices transfer to UiPath, n8n, or similar; the interesting part is the decisions, not PAD syntax.
Written 2026 for automation engineering roles. LinkedIn.
Prepared with LLM help for structure and prose cleanup from my notes and recorded explanations. Decisions, mistakes, and lessons are mine.