Skip to content

feat(tasks): return artifact download URL + agent env guidance - #74118

Merged
tatoalo merged 9 commits into
masterfrom
posthog-code/return-artifact-download-url
Jul 31, 2026
Merged

feat(tasks): return artifact download URL + agent env guidance#74118
tatoalo merged 9 commits into
masterfrom
posthog-code/return-artifact-download-url

Conversation

@posthog

@posthog posthog Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Problem

Two related agent-plumbing changes, combined into one PR:

  1. Artifact download URLs. Cloud agents upload deliverables (reports, screenshots, exports) as task-run artifacts via artifacts/finalize_upload, but the response returned no link to the file. The agent-side upload_artifact tool therefore couldn't hand back a URL, so an agent that produced a file had no way to reference or share it. This adds the backend half; the tool-side change is in a companion PostHog/code PR (Fix charts in dashboards #3862).
  2. Agent environment guidance. AGENTS.md implied the sandbox was a restricted patch-editing environment ("use flox when available" with no counter-signal), which led agents to assume they couldn't run tests/Storybook/the app and to ship visual changes with a written caveat instead of actually verifying them. This reframes it as a full dev environment.

Changes

Backend — presigned artifact URL

  • finalize_task_run_artifact_uploads now mints a presigned download URL per finalized artifact and attaches it to the response (url), mirroring the existing log_url presign pattern (object_storage.get_presigned_url).
  • The URL is response-only and not persisted on the run manifest, because presigned URLs are time-limited.
  • Added an optional url field to TaskRunArtifactResponseSerializer (with help_text). It's optional, so other responses reusing this serializer are unaffected — the field is simply omitted when absent.
  • Generated types (products/tasks/frontend/generated/*, services/mcp/src/api/generated.ts) were regenerated to pick up the field.

AGENTS.md — environment guidance

  • Adds three bullets to the Environment section: treat the sandbox as a full dev environment, install missing deps rather than assuming a wall, and for visual/UX changes actually render and compare rather than shipping a caveat. Worded as a method (try, then report a specific named failure) so it holds on a constrained sandbox too.

How did you test this?

I (Claude) linted the Python (ruff clean). The generated-type update was produced by the repo's OpenAPI codegen automation. I could not run the Django test suite in this sandbox (it needs a Postgres/dev stack that wasn't provisioned); the existing test_upload_artifacts* suite in products/tasks/backend/tests/ covers the finalize path and is where a url assertion belongs. The companion PostHog/code PR's upload_artifact unit test (which asserts the URL is surfaced) passes there.

Automatic notifications

  • Publish to changelog?
  • Alert Sales and Marketing teams?

Docs update

🤖 Agent context

Autonomy: Fully autonomous

Authored by Claude Code. Originated from a session where an agent (me) uploaded a Storybook screenshot via upload_artifact and found the tool returns no URL — and, separately, had earlier wrongly assumed it couldn't run Storybook at all. The two fixes address both: return a URL from the backend, and correct the environment guidance that produced the wrong assumption. Both were previously separate PRs; folded together here at the maintainer's request (the AGENTS.md change was #74021, now closed).

Design note: chose a presigned URL (matching the existing log_url pattern) over a durable auth-gated endpoint URL — immediately usable by the agent and publicly fetchable, with expiry as the tradeoff, noted in the code and the companion docs. Invoked the /improving-drf-endpoints skill before touching the serializer (optional field + help_text, no enum-collision-prone name). The backend change stays within the isolated tasks product (facade + presentation), crosses no product boundary, and touches no contracts.py. Companion: PostHog/code#3862.


Created with PostHog Code from an inbox report.

@posthog posthog Bot added the skip-agent-review Save $$$, skip auto agent reviews (Greptile) — use for trivial or chore PRs label Jul 28, 2026
@posthog posthog Bot changed the title feat(tasks): return presigned download URL on artifact finalize feat(tasks): return artifact download URL + agent env guidance Jul 28, 2026
@posthog
posthog Bot marked this pull request as ready for review July 28, 2026 11:23
@pr-assigner-resolver-posthog
pr-assigner-resolver-posthog Bot requested a review from a team July 28, 2026 11:24
@pr-assigner-resolver-posthog

Copy link
Copy Markdown

👀 Auto-assigned reviewers

These soft owners were skipped because they only have minor changes here. Nothing blocks merge, so self-assign if you'd like a look:

  • @PostHog/team-devex (owners.yaml)

Soft owners come from each directory's owners.yaml and each product's product.yaml (resolved nearest-file-wins). The locator after each owner is the file that decided it. Generated files and lockfiles are ignored when deciding ownership.

posthog Bot added 3 commits July 28, 2026 13:05
The artifacts/finalize_upload response now includes a presigned download URL for each finalized artifact, so callers (e.g. the upload_artifact agent tool) can link to the uploaded file directly.

The URL is minted per response via object_storage.get_presigned_url (mirroring the existing log_url presign pattern) and is deliberately not written back to the run manifest, since presigned URLs are time-limited. The new serializer field is optional, so responses that reuse TaskRunArtifactResponseSerializer without a URL are unaffected.

Note: products/tasks/frontend/generated/* must be regenerated with `hogli build:openapi` to pick up the new field. I could not run codegen in this sandbox — schema generation requires a running Postgres/dev stack that wasn't provisioned.

Generated-By: PostHog Code
Task-Id: d3757c3d-15f3-485a-b4f3-d0b760f78963
Fold the AGENTS.md environment guidance (previously PR #74021) into this PR: treat the sandbox as a full dev environment — install missing deps and run tests/Storybook/the app to verify — worded as a method so it holds on a constrained sandbox too.

Generated-By: PostHog Code
Task-Id: d3757c3d-15f3-485a-b4f3-d0b760f78963
@posthog
posthog Bot force-pushed the posthog-code/return-artifact-download-url branch from b5f1969 to 5478b91 Compare July 28, 2026 13:05
@github-actions

github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

🤖 CI report

Bundle size — no change

Uncompressed size of every built .js bundle, compared against the base branch.

Total: 65.43 MiB · no change

No file changed by more than 1000 B.

Posted automatically by build-bundle-size-report · uncompressed bytes from dist-report

Eager graph — within budget

How much code each root ships on the eager path — downloaded and parsed before the surface is interactive. Measured from the esbuild output chunks (post-tree-shake, static imports only); lazy import() / React.lazy chunks are not counted.

Root Eager (shipped) Δ vs base Budget
entry (logged-out pages, app bootstrap)
src/index.tsx
1.25 MiB · 22 files no change ███░░░░░░░ 27.7% of 4.51 MiB
authenticated shell (every logged-in page)
src/scenes/AuthenticatedShell.tsx
8.12 MiB · 3,023 files no change ████████░░ 83.6% of 9.71 MiB

🟢 node_modules/monaco-editor/ stays out of src/index.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 node_modules/monaco-editor/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx

Largest files eagerly shipped from src/index.tsx
Size File
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
24.6 KiB ../node_modules/.pnpm/buffer@6.0.3/node_modules/buffer/index.js
6.3 KiB ../node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.production.min.js
4.5 KiB ../node_modules/.pnpm/@jspm+core@2.1.0/node_modules/@jspm/core/nodelibs/browser/process.js
3.9 KiB ../node_modules/.pnpm/scheduler@0.23.2/node_modules/scheduler/cjs/scheduler.production.min.js
1.4 KiB ../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js
1.3 KiB src/RootErrorBoundary.tsx
912 B ../node_modules/.pnpm/ieee754@1.2.1/node_modules/ieee754/index.js
789 B src/scenes/ChunkLoadErrorBoundary.tsx
762 B src/index.tsx
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
Size File
285.3 KiB ../node_modules/.pnpm/posthog-js@1.409.2/node_modules/posthog-js/dist/rrweb.js
267.7 KiB ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
235.5 KiB src/taxonomy/core-filter-definitions-by-group.json
231.4 KiB ../node_modules/.pnpm/posthog-js@1.409.2/node_modules/posthog-js/dist/module.js
154.3 KiB ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
105.2 KiB src/lib/api.ts
94.7 KiB ../packages/quill/packages/quill/dist/index.js
93.3 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js
90.6 KiB ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js

Posted automatically by check-eager-graph · sizes are eager output bytes (shipped, post-tree-shake) from the esbuild metafile · part of #32479

Toolbar bundle — eager 2.19 MiB within budget

What the toolbar ships to customer pages, measured from the esbuild output (minified, post-tree-shake). The eager set is the entry plus everything statically imported from it — fetched before any feature runs; deferred chunks load lazily. The eager guardrail is 5.72 MiB. Each output file must also stay below 10 MB, where CloudFront stops compressing it. The module boundary is enforced separately by check-toolbar-graph.

Metric Size Δ vs base Budget
Eager (shipped)
entry + static imports
2.19 MiB · 17 files no change ████░░░░░░ 38.3% of 5.72 MiB
Deferred (lazy) 2.08 MiB · 33 files no change n/a — loads on demand
Loader dist/toolbar.js 1.1 KiB no change █░░░░░░░░░ 5.8% of 19.5 KiB
Largest eagerly-shipped chunks
Size File
717.8 KiB dist/toolbar/toolbar-app-2QFKEBT7.css
551.1 KiB dist/toolbar/chunk-chunk-5FDJUV5A.js
484.6 KiB dist/toolbar/chunk-chunk-QCKKTYHY.js
133.6 KiB dist/toolbar/chunk-chunk-UDBJ4EGL.js
131.8 KiB dist/toolbar/chunk-chunk-T5KY5WYR.js
71.0 KiB dist/toolbar/toolbar-app-DBANC7W5.js
69.0 KiB dist/toolbar/chunk-chunk-27JL52RE.js
35.6 KiB dist/toolbar/chunk-chunk-QFZQEUXB.js
20.9 KiB dist/toolbar/chunk-chunk-HWIVFWBZ.js
12.2 KiB dist/toolbar/chunk-chunk-PIK3PADE.js

Posted automatically by check-toolbar-size · sizes are toolbar output bytes (shipped, post-tree-shake) from the esbuild metafile

Dist folder size — 🔺 +636 B (+0.0%)

Total size of the built frontend/dist folder (all assets), compared against the base branch.

Total: 1371.02 MiB · 🔺 +636 B (+0.0%)

finalize_task_run_artifact_uploads now returns a presigned url on each response entry (not persisted to the manifest), so the idempotent-path test can no longer assert the response equals the stored manifest verbatim. Compare the stored fields separately from the URL and assert a URL is present, preserving the idempotency guarantee (existing entry returned unchanged, no re-head/re-tag).

Generated-By: PostHog Code
Task-Id: d3757c3d-15f3-485a-b4f3-d0b760f78963
@trunk-io

trunk-io Bot commented Jul 28, 2026

Copy link
Copy Markdown

😎 Merged manually by @tatoalo - details.

@tatoalo tatoalo self-assigned this Jul 30, 2026
@tatoalo
tatoalo enabled auto-merge (squash) July 30, 2026 12:16
@tatoalo tatoalo added stamphog Request AI approval (no full review) and removed skip-agent-review Save $$$, skip auto agent reviews (Greptile) — use for trivial or chore PRs labels Jul 31, 2026
@stamphog

stamphog Bot commented Jul 31, 2026

Copy link
Copy Markdown

stamphog does not review bot-authored PRs — removing the stamphog label. This change needs a human reviewer.

@stamphog stamphog Bot removed the stamphog Request AI approval (no full review) label Jul 31, 2026
@tatoalo
tatoalo merged commit b6a2f2b into master Jul 31, 2026
246 checks passed
@tatoalo
tatoalo deleted the posthog-code/return-artifact-download-url branch July 31, 2026 10:14
@deployment-status-posthog

deployment-status-posthog Bot commented Jul 31, 2026

Copy link
Copy Markdown

Deploy status

Environment Status Deployed At Workflow
dev ✅ Deployed 2026-07-31 10:45 UTC Run
prod-us ✅ Deployed 2026-07-31 11:03 UTC Run
prod-eu ✅ Deployed 2026-07-31 11:05 UTC Run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant