Files
wyndham-ARR/.project-docs/50-evidence/topics/2026-07-30-superagent-fetch-oss-prompt-experiment.md
2026-07-31 15:11:42 +08:00

13 KiB
Raw Blame History

SuperAgent fetch_oss_file Prompt Experiment

Scope

Use the first fresh controlled ARR trace together with historical successful SuperAgent fetches to separate Agent orchestration behavior, address shape and platform file-type policy.

Evidence

  • The controlled ARR job reached the intended SuperAgent Agent with its generated PROGRAM_INPUT and invoked fetch_oss_file four times.
  • The trace shows that the runtime Tool accepted object_uri and optional filename arguments. The first OSS shorthand request returned public_endpoint_missing; later HTTPS variants for the XML returned extension_not_allowed. These are Provider results, not Tool Schema validation failures.
  • The Agent also read the Skill and used shell inspection before fetch success, despite the prior concise Prompt's stop rule. The four calls were four Agent tool decisions inside one remote run, not four ARR submissions or transport retries.
  • Historical exported conversations contain successful fetch_oss_file calls for .xlsx attachments. They returned a local file under the runtime uploads directory in about 220 seconds. Those inputs included a direct OSS HTTPS URL, but the exports do not expose the raw Tool Call arguments and do not prove that .xml is allowed in the ARR Agent's Provider configuration.
  • No public upstream source or official documentation containing the two Provider error codes was found; this appears to be a platform-specific Tool.

Historical Prompt Change (superseded)

The first corrective Main Prompt made fetch the only permitted tool action before a local source file exists and specifies exactly one call:

object_uri = "oss://" + attachment.oss.bucket + "/" + attachment.oss.object_key
filename   = attachment.name

It forbids parallel Skill/reference reads, filesystem/environment inspection, URI substitution, argument repair, shell/curl/SDK fallback and every second fetch. Any Provider failure, ambiguous result or missing unique local path must produce one failed Profile object and end the run.

The Prompt is 1,757 characters, remains below the existing 1,800-character regression limit, and all 12 tests.test_arr_opera_daily_ingest tests pass.

Interpretation at that stage

This was a bounded diagnostic Prompt experiment. It removed retries and side-path noise but still used the wrong oss:// address form.

After this Prompt is published, one fresh controlled ARR job has decisive outcomes:

  1. One successful fetch returning one local XML path: continue to verify the Skill and MCP stages.
  2. One public_endpoint_missing: confirm whether the Tool expects a public HTTPS address before assuming it needs a credential-backed Provider.
  3. One extension_not_allowed: add .xml/application/xml to the Provider's allowed source types; do not keep tuning the Prompt.
  4. More than one fetch or any pre-fetch shell/Skill read: the published Prompt was not selected or the model did not obey it; verify Profile version and runtime trace before any Provider change.

Published Prompt Follow-up Run

Controlled job arrjob-737acd9d35d04d7f9bcbbc60e7674236 reached remote run 53510877-e30a-4f44-9a6c-26980cdc9461 with the intended PROGRAM_INPUT. The available trace snapshot shows:

  • exactly one model-selected tool action: fetch_oss_file with object_uri and filename=source.xml;
  • no read_file, shell, Skill processor, present_files, or arr_submit_processing_result action before or after that fetch in the captured events;
  • one Provider result with success=false, error=public_endpoint_missing, and message Public OSS endpoint is not configured;
  • no HTTPS substitution and therefore no new extension_not_allowed result.

This validates the Prompt's single-call/no-bypass behavior for the captured portion and makes the Agent-specific Provider endpoint the first actionable blocker. The supplied snapshot was refreshed about 20 seconds after the Tool result and still ended with status=running; it contains no message.final or terminal run event, so it does not yet prove final failure-object emission or ARR terminalization. A later trace snapshot is required for that separate check.

Public-read URL correction

The user subsequently confirmed two authoritative deployment facts:

  • fetch_oss_file reads a publicly accessible OSS URL and does not need a Provider;
  • the ARR OSS deployment is public-read.

The local implementation therefore replaces the historical oss:// experiment:

  • PROGRAM_INPUT is now arr-opera-daily-program-input-3 with required oss.url;
  • ARR generates https://{bucket}.oss-{region}.aliyuncs.com/{encoded-object-key} with no query signature;
  • the 1,682-character Prompt copies oss.url to object_uri and source.xml to filename exactly once;
  • only committed source XML has public-read object ACL; staged objects and processing outputs remain private;
  • OSS readiness requires the approved public-read bucket.

Forty-four targeted tests and the complete 276-test suite pass with two expected skips. No fresh platform run has exercised this contract yet. The next controlled trace should no longer return public_endpoint_missing. If it returns the previously observed extension_not_allowed, .xml/application/xml must be enabled in the platform Tool; more Prompt retries or URI substitutions would not solve that policy failure.

Mixed-version local run

The next attempted local job, arrjob-1fd0f5e182eb4056af53be7300174981, did not exercise this correction. Its complete available snapshot ended about seven seconds after run.started, still in middleware processing, with no object_uri, Tool call, Tool result, Skill load, MCP submission or terminal event. The serialized input was PROGRAM_INPUT v2 because the local 8765 process had started before the v3 files were modified. After the validated listener was restarted, all local readiness flags returned true. Acceptance therefore moves to one new job generated by the restarted process; the mixed-version job must not be used as v3 evidence.

First true v3 controlled run

Job arrjob-3c2cd75568554b0ab6d17817d446fed1 provided decisive evidence:

  • middleware input contained arr-opera-daily-program-input-3 and no v2 contract;
  • the model selected exactly one fetch_oss_file call with a redacted URL and filename=source.xml;
  • the Tool returned success=false, error=extension_not_allowed and no artifact;
  • the Agent made no second fetch, shell/SDK bypass, Skill call or MCP submission;
  • SuperAgent emitted run.completed with remote status success, meaning the orchestration run ended, not that business ingestion succeeded;
  • direct submissions, deliveries, Finance versions and outbox events remained zero.

Because an extension check can precede network download, ARR separately issued an anonymous HEAD without logging the object URL or reading its body. OSS returned HTTP 200, Content-Type: application/xml and Content-Length: 629434, exactly matching the registered source. ARR URL generation, object ACL and public reachability are therefore verified; the platform XML allowlist is the sole current fetch blocker.

The failure path also exposed two independent defects. The Agent returned only job_id, source_file_id, a minimal processor_result and files=[], which does not satisfy the Profile output object's required fields or object-shaped files. ARR still reported status=running 145 seconds after run.completed, because no MCP submission arrived and remote finalization is not yet projected into a terminal ARR failure. Neither defect should be addressed by URI retries or renaming the XML.

Frozen RUNNING diagnosis

A later read-only inspection distinguished a stale ARR state from an active Agent run:

  • the page continued polling every four seconds and its refreshed_at changed, but two trace samples stayed at 73 events;
  • the last persisted Agent event was AGENT_TRACE_STREAM_ENDED at 11:42:26 +08, three seconds after remote run.completed;
  • a read-only remote run lookup reported success, while the authoritative ARR run and attempt remained running with no finish time;
  • the trace JSONL was fully drained and no longer changing; direct submissions, artifact deliveries, Finance versions and outbox events were all zero;
  • the Agent-side business result was a safe failure code, extension_not_allowed, not an in-progress computation.

The production upload path constructs ProcessingRunner but calls only start(). No production component invokes poll() or otherwise reconciles a terminal remote run that never calls MCP. Even if polling were wired, the runner's delivery_missing transition is not recognized by PostgresProcessingState. The available stale-expiry helper is also not scheduled and applies to existing submission rows, whereas this run created none. Consequently this task will remain running until separately authorized repair logic or a guarded one-off repair is applied. Diagnosis did not change state, retry the stream, submit another XML or restart a service.

Main-flow impact assessment

The stale running state is not currently a report-generation gate:

  • every upload creates a new independent job id, and the upload control is gated by runtime readiness rather than another job's status;
  • Finance facts are written only inside an accepted MCP submission transaction, not by polling or task-log state;
  • current monthly and analytics readers consume committed Finance facts and do not wait for all processing jobs to become terminal;
  • at this historical ARR1 snapshot, automatic post-commit monthly dispatch was still absent, so no worker was blocked by this stale job. ARR2 later implemented a separate worker under ADR-001.

Terminal reconciliation would still improve operational correctness: accurate failure state, bounded retry semantics, idempotent failure notification and earlier revocation of an unused writeback grant. It does not make a failed XML run produce Finance facts or a report. At that snapshot, the immediate business-flow priorities were platform XML allowlisting, a successful MCP commit and the accepted automatic report-trigger implementation; the later run below supersedes the allowlist diagnosis while leaving the reconciler as separate control-plane hardening.

First successful fetch/process and rejected direct submission

Job arrjob-ae1a40b69c46402fb80e55c980b84886 proves that the platform XML allowlist was changed successfully and moves the failure boundary beyond OSS ingestion:

  • PROGRAM_INPUT v3 caused exactly one fetch_oss_file call. The Tool returned /mnt/user-data/uploads/source.xml, application/xml, 629434 bytes and SHA-256 b0019ba8ecdaad878bbde463b0c3129994bf582da16d9caf56d6b96da9a2db2a, exactly matching ARR registration.
  • The Agent loaded the intended Skill and references and invoked process_daily.py once. Its successful result reported 135 source rows, 16 excluded rows, 119 output rows and channel counts 26/25/54/14.
  • The generated structured-result.json passed the Agent's own key check with 135 records, zero errors and a compact size of 124493 characters.
  • Instead of passing that object through once, the Agent repeatedly reopened, printed, compacted and range-read the file. The captured sequence includes extra shell inspections, a temporary serialization, a full-file read and a later start_line=1200,end_line=2500 read.
  • The supplied trace snapshot was not a terminal log: it was copied at 12:41:02 +08 with status=running, after the trace connection had failed at 12:40:15 +08. A later read-only ARR trace projection shows the actual terminal state at 12:41:40 +08.
  • Exactly one MCP submission then reached ARR, proving active Tool discovery, network reachability and grant acceptance. ARR recorded only 20 submitted records, rejected the request as RESULT_CONTRACT_INVALID, wrote no Finance version, terminalized the job as failed and queued one downstream failure event.

The submitted payload therefore was not the complete 135-record object produced by the deterministic Skill. This is not an OSS, XML allowlist, Skill or MCP reachability problem, and another URI or fetch retry cannot change it. The current contract makes the model reproduce roughly 124 KB of JSON inside one tool-call argument after receiving that file through bounded model/tool context. Prompt wording can discourage the observed rereads, but cannot make exact large-payload transport reliable.

The durable options are either (1) let an installed platform-side submission adapter consume a sandbox file without serializing it through model output, or (2) make the MCP call a compact attempt-bound completion signal and let ARR use the deterministic source replay it already performs as the canonical structured payload. A remote MCP server cannot resolve an Agent-local /mnt/... path by itself, so merely replacing payload with payload_path in the current remote schema would not work.