Skip to content

Expose live visibility (matching console UI) for apply-pipeline agents (Tailor/Runner) over MCP #971

Closed

Description

@proagentstore

Problem:
The application pipeline (Application Tailor and Application Runner / Job Application Assistant) has no MCP-level visibility into what's actually happening during a tailoring or filling run. list_applications / get_application only expose a static status field (e.g. "tailoring", "filling", "blocked"), with no equivalent of coding_session_capture / coding_timeline that coding agents get.

However, the console UI already shows live progress for these browser-driving apply agents while a run is in progress. That same data is not exposed through MCP.

Request:
Add an MCP tool (or extend get_application) for Tailor and Runner instances that surfaces the same live run detail already rendered in the console UI — what the agent is currently doing/seeing in its browser or tailoring session — in real time, analogous to coding_session_capture/coding_timeline for coding agents.

Context: this was raised after two application tailoring runs were blocked with runner_rejected ("already tailoring 1 application(s) for this agent, limit 1") with no way to inspect what the active run was doing, or how close it was to finishing, short of polling get_application's status field.

Filed from owner feedback on instances 19b2e410-394a-4485-b832-6005356e7766 (Application Tailor) and 2e85124f-4946-49d2-b922-8636ba92ca6a (Application Runner).

Activity

  1. proagentstore commented on Oct 8, 2026

    @proagentstore
    Author

    Concrete real example of this gap, from application 435d31c8-01a4-48d7-87f2-08584fa6d02e (Head of Engineering @ Business AI Group):

    Tailoring (Application Tailor, instance 19b2e410-394a-4485-b832-6005356e7766) completed cleanly — résumé + cover letter written, 36/36 claims matched, run.ended status completed.

    The application then handed off to the Application Runner (instance 2e85124f-4946-49d2-b922-8636ba92ca6a) to fill the SEEK application form. application_trace for this run shows only: run.requested → policy.submit_gate → runner.dispatched → source.read → engine.started → engine.ended (exitCode 0) → run.ended (status: blocked, reason: incomplete).

    That is the ENTIRE record of a 51-second browser session. There is no indication of: which page(s) it navigated to, which form fields it filled or attempted to fill, where in the form it stopped, or why it considered the submission incomplete.

    Critically: the console UI for this same run DOES show screenshots and what looks like a transcript of the browser session while/after it ran. That data exists and is being captured — it is simply not exposed through any MCP tool. application_trace and get_application only ever surface the coarse lifecycle/engine events above, never the page-by-page or field-by-field browser actions the UI renders.

    This is the exact case the Runner should expose via MCP: when a fill run ends blocked/incomplete with no code-level error, the owner currently has no way via API/MCP to find out what the agent actually did on the site before stopping — they'd have to go look at the console UI screenshots/transcript by hand. Whatever backs that UI view (screenshots, page transcript, step log) should be readable through MCP, the same way coding_session_capture/coding_timeline expose a coding agent's terminal.

  2. serge-ivo commented on Oct 8, 2026

    @serge-ivo
    Contributor

    Implemented in 2b9a2fd — four read-only MCP tools, live where the route is live.

    Tool Answers Live?
    application_runs a Runner's fill runs, newest first — which run holds the concurrency slot —
    application_run ONE fill run as it stands now (the coding_session_capture counterpart) yes
    application_run_supervision each checkpoint's facts + the one directive recorded for it yes
    tailoring_run a Tailor's run: policy, result, trace yes, while running

    application_run returns the run's status, pause (what it waits for and the questions it asked), policy with mode/limits/allowed domains and every submit-gate check with its verdict, result (outcome, fields filled, uploads, whether a submit was attempted), engineAuth, runnerNode, errors, timings, and the runner event trace — browser.navigated, field.filled, artifact.uploaded, policy.decision, browser.blocked, submit.*, supervisor.* — each with its runnerSeq, plus the application and its lifecycle audit. tailoring_run carries artifact handles, never résumé or cover-letter text.

    The three live reads pull the owner's machine before answering, so a just-emitted event is already in the reply. All four are reads: scope read, GET only (asserted in the test) — a live view starts, resumes and dispatches nothing.

    The gap was real, and it was exactly this: not one MCP tool reached /application-runs/* or the Tailor's /applications/:id. Everything above was HTTP-reachable and reachable nowhere else.

    Two claims in this issue don't match the code, and they change what this can promise. Both verified:

    1. The console does not show screenshots or a transcript for these runs. ApplicationsTab.tsx's only per-application read is /application-queue/:id/trace (line 159) — exactly what application_trace already returned; it never calls /application-runs/*. The screenshot-replay page is pages/RunDetail.tsx, which its own header scopes to "any browser-runtime task" (RuntimeTask/RuntimeEvent + lib/run-shots.ts) — the legacy JOB_APPLY path, retired for new starts in 651bdd1. Nothing under lib/local-apply/ or browser-runner/src/local-apply/ captures a screenshot at all. What you saw was almost certainly an older Job Application Assistant run's replay, not this Runner's.

    2. application_trace was hiding nothing. lib/applications/control.ts folds in every event from local_apply_runs.trace unfiltered. Had browser.navigated/field.filled been recorded for application 435d31c8, they would already have appeared there.

    So for that specific 51-second run, the page-by-page detail does not exist server-side. The bridge does emit those events (bridge.ts — navigated, field.filled, artifact.uploaded, review.ready), but only when the CLI calls a bridge tool. That engine started and exited 0 having called none — which is itself why the run ended blocked/incomplete. A trace holding only engine.started/engine.ended is therefore a finding, not a hole in this tool, and application_run's description says exactly that so a reader stops hunting for a record that was never written.

    What would close that last gap, and why I did not do it here: the CLI's own stdout is kept on the machine (local-apply/runtime.ts) and deliberately never crosses the runner contract — LocalApplyStatusResponse carries state/pause/events/lastSeq/result, and result.summary is the only part derived from that output which reaches the cloud. Shipping a bounded engine-output tail would answer "what did the CLI do when it called nothing", but it needs a runner-contract change, a CLI release, and a privacy decision: CLI prose can contain profile values, which is why the contract excludes it today. Worth its own issue if you want it.

    MCP 0.1.94: 275 registrations → 279 (always-on 249 → 253, gated unchanged), lock entry appended, with the manifest, docs, README, operator skills and about page following.

    Verification: full suite 855 files / 14,381 tests green; biome, all three tsconfig.test.json typechecks, MCP parity, docs:drift, file-size, surface-lock --require-history and OpenAPI 406/406 all clean. CI for 2b9a2fd was still queued when this was written.

  3. added 2 commits that reference this issue on Oct 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions