Skip to content

feat(max): add image attachments#12

Open
lordspline wants to merge 2 commits into
masterfrom
capy/max-image-attachments
Open

feat(max): add image attachments#12
lordspline wants to merge 2 commits into
masterfrom
capy/max-image-attachments

Conversation

@lordspline

@lordspline lordspline commented Jun 17, 2026

Copy link
Copy Markdown

Problem

Users need to share screenshots with PostHog AI for context about their data, dashboards, or error states. The existing attachment system (UploadedMedia) is public/unauthenticated and unsuitable for AI conversations, which may contain private product data.

Changes

Backend

  • Added ConversationAttachment model with team/user/conversation scoping, status tracking, and indexes for efficient queries
  • Created /api/projects/:team_id/conversation_attachments/ endpoints for multipart upload and delete with authorization checks
  • Implemented server-side PNG/JPEG signature validation, Pillow verification, and 4 MiB/file + 12 MiB/total limits
  • Stored files in S3-compatible object storage using existing posthog/storage/object_storage wrappers
  • Added attachment reference validation before committing to Temporal workflows
  • Implemented cleanup for abandoned pending uploads (>24h old)

Model conversion

  • Extended HumanMessage schema with attachments field carrying small authorized references
  • Updated Anthropic and OpenAI message converters to resolve references server-side and emit multimodal blocks
  • Hard-redacted image base64 and data URLs in AI telemetry truncation before size limits (prevents leaks into $ai_generation traces)

Frontend

  • Added file picker, drag/drop, and clipboard paste support in QuestionInput component with visual preview chips
  • Implemented pending attachment state in maxThreadLogic with upload progress, error handling, and retry logic
  • Added upload protection (disabled submit while uploading/errors exist) and double-submit prevention
  • Used generated API functions (conversationAttachmentsCreate, conversationAttachmentsDestroy) from OpenAPI

Other

  • Added PostgreSQL migration 0004_conversation_attachments.py
  • Updated assistant message schema enums (ContentType.IMAGE_PNG, ContentType.IMAGE_JPEG)
  • Scaffolded MCP tool entries (disabled by default as file upload is a user UI capability, not an agent tool)
  • Added 134 backend tests and 113 frontend tests covering attachment lifecycle, validation, and integration

How did you test this code?

  • Backend tests: ee/hogai/utils/test/test_anthropic.py, ee/hogai/utils/test/test_openai.py, ee/api/test/test_conversation.py, products/posthog_ai/backend/api/test_conversation_attachments.py, ee/hogai/core/test/test_ai_event_truncation.py — 134 passed
  • Frontend tests: frontend/src/scenes/max/maxThreadLogic.test.ts, frontend/src/scenes/max/components/QuestionInput.test.tsx — 113 passed, TypeScript check passed
  • E2E flow: uploaded screenshot, removed/re-added, sent to assistant, verified assistant received image context with has_image=true in /v1/messages?beta=true request

👉 Stay up-to-date with PostHog coding conventions for a smoother review.

Automatic notifications

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

Docs update

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Implemented safe v1 PNG/JPEG screenshot attachments for PostHog AI per issue PostHog#62926. Key architectural decisions:

  • Built a new PostHog AI-specific attachment path (ConversationAttachment model) instead of reusing UploadedMedia, which is intentionally public/unauthenticated
  • Used authorized object-storage references (small DB rows) in queue/Temporal payloads instead of large image bytes to stay below Temporal payload limits
  • Validated attachments server-side on send (team, user, conversation, status, count, total size) to prevent privilege escalation
  • Hard-redacted image base64/data URLs in AI telemetry truncation before enforcing size limits, keeping screenshots out of $ai_generation traces
  • Scoped MCP tools as disabled (enabled: false) because file upload is a user UI capability, not an agent tool capability

All generated schema/API/MCP artifacts were regenerated from the backend changes. Tests cover the full lifecycle from UI upload through model gateway.

Open POST-035 POST-035


View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
@lordspline lordspline added the capy Generated by capy.ai label Jun 17, 2026 — with Capy AI
Comment thread ee/api/conversation.py
attachment_ids=serializer.validated_data.get("attachment_ids", []),
)
except AttachmentNotFoundError as error:
raise serializers.ValidationError({"attachment_ids": str(error)}) from error
Comment thread ee/api/conversation.py
except AttachmentNotFoundError as error:
raise serializers.ValidationError({"attachment_ids": str(error)}) from error
except AttachmentValidationError as error:
raise serializers.ValidationError({"attachment_ids": str(error)}) from error
Comment thread ee/api/conversation.py
attachment_ids=serializer.validated_data.get("attachment_ids", []),
)
except AttachmentNotFoundError as error:
raise serializers.ValidationError({"attachment_ids": str(error)}) from error
Comment thread ee/api/conversation.py
except AttachmentNotFoundError as error:
raise serializers.ValidationError({"attachment_ids": str(error)}) from error
except AttachmentValidationError as error:
raise serializers.ValidationError({"attachment_ids": str(error)}) from error
uploaded_file=uploaded_file,
)
except AttachmentValidationError as error:
raise serializers.ValidationError({"file": str(error)}) from error

@capy-ai capy-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added 7 comments

Comment thread products/posthog_ai/backend/attachments.py Outdated
Comment thread products/posthog_ai/backend/attachments.py Outdated
Comment thread ee/api/conversation.py
Comment thread ee/api/conversation.py Outdated
Comment thread products/posthog_ai/backend/attachments.py Outdated
Comment thread products/posthog_ai/frontend/generated/api.ts
Comment thread frontend/src/scenes/max/maxThreadLogic.tsx Outdated
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

capy Generated by capy.ai

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants