Skip to content

feat: capture_ai public beta - #869

Merged
carlos-marchal-ph merged 2 commits into
mainfrom
feat(aio)/capture-ai-public-beta
Aug 13, 2026
Merged

feat: capture_ai public beta#869
carlos-marchal-ph merged 2 commits into
mainfrom
feat(aio)/capture-ai-public-beta

Conversation

@carlos-marchal-ph

@carlos-marchal-phcarlos-marchal-ph commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

💡 Motivation and Context

Takes the AI capture lane public as a beta, per RFC 1198 and the cross-SDK contract in sdk-specs (capture-ai capability, branch feat(aio)/add-capture-ai). The private _capture_ai (shipped since 7.29.0) becomes capture_ai — public on Client and module level, returning the event UUID — and the two private flags collapse into one public enable_full_ai_capture (wrapper routing + no truncation + media passthrough; privacy_mode always wins), with _use_ai_lane / _enable_multimodal_capture kept as silent deprecated aliases for the transition window. capture_ai returns the captured event's UUID (a client-generated one when the caller supplies none), which is what makes at-least-once delivery dedupe-safe. The compliance adapter opts into the new capture_ai harness suite (capture_ai_v0).

💚 How did you test it?

  • New/updated unit tests: UUID return + wire equality + supplied-uuid preservation, flag matrix, alias mapping (constructor / properties / module-global setup() sync), privacy-mode-wins, lane isolation both directions. posthog/test/test_ai_capture_lane.py green; full make test green (pre-existing env-only failures identical on base).
  • make public_api_check clean; snapshot regenerated.
  • End-to-end: posthog-sdk-test-harness capture_ai suite 4/4 against this branch's compliance adapter.

📝 Checklist

  • I reviewed the submitted code.
  • I added tests to verify the changes.
  • I updated the docs if needed. (docs PR on posthog.com, branch feat(aio)/capture-ai-docs)
  • No breaking change or entry added to the changelog.

If releasing new changes

  • Ran sampo add to generate a changeset file

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

  • Authored with PostHog Code (Claude), directed by Carlos Marchal; implementation, tests, and cross-repo consistency checks were agent-executed with human review gates.
  • Key decisions: one flag instead of splitting fidelity/media/routing knobs (large-event cases move together); UUID generation left to the shared capture path (a UUIDv7 upgrade was reverted as out of scope — one for the client-libraries fleet migration); deprecated flags aliased via properties so direct attribute writes keep working through the transition window.

Created with PostHog Code

Generated-By: PostHog Code
Task-Id: 4b5e5cda-81f1-41a2-8fcd-4f335d19217e
@carlos-marchal-ph
carlos-marchal-ph requested a review from a team as a code ownerAugust 12, 2026 12:41
@github-actions

github-actionsBot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

posthog-python Compliance Report

Date: 2026-08-13 09:41:54 UTC
Duration: 256515ms

✅ All Tests Passed!

111/111 tests passed


Capture_V1 Tests

94/94 tests passed

View Details
TestStatusDuration
Endpoint And Method.Targets V1 Endpoint518ms
Endpoint And Method.Does Not Use Legacy Endpoints511ms
Required Headers.Has Authorization Bearer Header511ms
Required Headers.Has Content Type Json510ms
Required Headers.Has Posthog Sdk Info Format512ms
Required Headers.Has Posthog Attempt Header510ms
Required Headers.Has Posthog Request Id511ms
Required Headers.Has Posthog Request Timestamp510ms
Required Headers.Has User Agent511ms
Body Format.Body Has Created At And Batch511ms
Body Format.No Api Key In Body510ms
Body Format.No Sent At In Body511ms
Event Format.Event Has Required Root Fields511ms
Event Format.Event Uuid Is Valid511ms
Event Format.Event Timestamp Is Rfc3339512ms
Event Format.Distinct Id Is String510ms
Event Format.Distinct Id At Root Not Properties511ms
Event Format.Custom Properties Preserved511ms
Event Format.Set Properties Preserved511ms
Event Format.Set Once Properties Preserved511ms
Event Format.Groups Properties Preserved511ms
Event Format.Sdk Generates Uuid If Not Provided510ms
Event Format.Event Has Required Root Fields Batch514ms
Event Format.Event Uuid Is Valid Batch514ms
Event Format.Event Timestamp Is Rfc3339 Batch515ms
Event Format.Distinct Id Is String Batch514ms
Event Format.Distinct Id At Root Not Properties Batch514ms
Event Format.Custom Properties Preserved Batch514ms
Event Format.Set Properties Preserved Batch515ms
Event Format.Set Once Properties Preserved Batch514ms
Event Format.Groups Properties Preserved Batch515ms
Event Format.Sdk Generates Uuid If Not Provided Batch514ms
Batch Behavior.Multiple Events In Single Batch518ms
Batch Behavior.Batch Envelope Smoke516ms
Batch Behavior.Flush With No Events Sends Nothing506ms
Batch Behavior.Flush At Triggers Batch1012ms
Batch Behavior.Created At Reflects Batch Creation Time512ms
Deduplication.Generates Unique Uuids518ms
Deduplication.Different Events Same Content Different Uuids513ms
Deduplication.Preserves Uuid On Retry6517ms
Deduplication.Preserves Timestamp On Retry6520ms
Deduplication.Preserves Uuid And Timestamp On Batch Retry6520ms
Deduplication.No Duplicate Events In Batch519ms
Header Behavior On Retry.Attempt Header Starts At One511ms
Header Behavior On Retry.Attempt Header Increments On Retry13522ms
Header Behavior On Retry.Request Id Preserved On Retry6520ms
Header Behavior On Retry.Different Requests Have Different Request Ids3021ms
Header Behavior On Retry.Request Timestamp Changes On Retry6519ms
Response Format Validation.Success Response Has Uuid Keyed Results511ms
Response Format Validation.Success Response Has Ok For Each Event515ms
Response Format Validation.Success No Retry After When All Ok513ms
Response Format Validation.Success Retry After Present When Retry Events1516ms
Response Format Validation.Success No Retry After When Drop Only513ms
Response Format Validation.Response Echoes Request Id511ms
Retry Behavior.Retries On 4086521ms
Retry Behavior.Retries On 5006520ms
Retry Behavior.Retries On 5038520ms
Retry Behavior.Retries On 5046520ms
Retry Behavior.Retryable Errors Have Retry After3518ms
Retry Behavior.Respects Retry After On Retryable Error11523ms
Retry Behavior.Does Not Retry On 4002514ms
Retry Behavior.Does Not Retry On 4012514ms
Retry Behavior.Does Not Retry On 4022514ms
Retry Behavior.Does Not Retry On 4132514ms
Retry Behavior.Does Not Retry On 4152514ms
Retry Behavior.Non Retryable Errors Have No Retry After2514ms
Retry Behavior.Implements Backoff22537ms
Retry Behavior.Max Retries Respected22534ms
Partial Batch Handling.Handles 200 Full Success2514ms
Partial Batch Handling.Handles 200 With All Ok3517ms
Partial Batch Handling.Does Not Retry Dropped Events3518ms
Partial Batch Handling.Does Not Retry Limited Events3514ms
Partial Batch Handling.Prunes Ok Events On Partial Retry6523ms
Partial Batch Handling.Prunes Dropped Events On Partial Retry6521ms
Partial Batch Handling.Retries Only Retry Events From Partial6523ms
Partial Batch Handling.Partial Retry Preserves Uuids6523ms
Partial Batch Handling.Partial Retry Attempt Header Increments6522ms
Partial Batch Handling.Partial Retry Request Id Preserved6523ms
Partial Batch Handling.Respects Retry After On Partial8523ms
Partial Batch Handling.Unknown Result Treated As Terminal3517ms
Partial Batch Handling.Mixed Ok Drop Limited No Retry3519ms
Compression.Sends Gzip Content Encoding512ms
Compression.No Content Encoding When Disabled511ms
Compression.Compressed Body Is Decompressible511ms
Error Handling.Does Not Retry On Unknown 4Xx2513ms
Event Options.Cookieless Mode Override512ms
Event Options.Disable Skew Correction Override511ms
Event Options.Process Person Profile Override511ms
Event Options.Product Tour Id Override511ms
Event Options.Unset Options Omitted510ms
Event Options.Options Override In Batch515ms
Geoip And Historical Migration.Geoip Disable Injected Into Properties511ms
Geoip And Historical Migration.Historical Migration Set In Body511ms
Geoip And Historical Migration.Historical Migration Absent By Default511ms

Feature_Flags Tests

17/17 tests passed

View Details
TestStatusDuration
Request Payload.Request With Person Properties Device Id12ms
Request Payload.Flags Request Uses V2 Query Param11ms
Request Payload.Flags Request Hits Flags Path Not Decide11ms
Request Payload.Flags Request Omits Authorization Header10ms
Request Payload.Token In Flags Body Matches Init11ms
Request Payload.Groups Round Trip11ms
Request Payload.Groups Default To Empty Object11ms
Request Payload.Disable Geoip False Propagates As Geoip Disable False12ms
Request Payload.Disable Geoip Omitted Defaults To False11ms
Request Payload.Flag Keys To Evaluate Contains Only Requested Key12ms
Request Lifecycle.No Flags Request On Init Alone4ms
Request Lifecycle.No Flags Request On Normal Capture511ms
Request Lifecycle.Two Flag Calls Produce Two Remote Requests16ms
Request Lifecycle.Mock Response Value Is Returned To Caller11ms
Retry Behavior.Retries Flags On 502316ms
Retry Behavior.Retries Flags On 504314ms
Side Effect Events.Get Feature Flag Captures Feature Flag Called Event513ms

@greptile-apps

Copy link
Copy Markdown
Contributor
Prompt To Fix All With AI
### Issue 1
posthog/client.py:1503
**AI events retain UUIDv4 fallback**
When `capture_ai` is called without a UUID, it delegates to the shared `_capture` and `_enqueue` path, which generates a UUIDv4. The returned and transmitted identifier therefore violates the new capture-ai UUIDv7 contract and lacks the intended time-ordering semantics.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "feat: capture ai public beta" | Re-trigger Greptile

Comment threadposthog/client.py

@marandanetomarandaneto left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Automated review findings.

Comment threadposthog/client.py
Internal and experimental, with no stability guarantees: the signature
and lane behavior may change while the AI capture lane is validated on
PostHog's own traffic.
Takes the same arguments and returns the same value as `capture()`:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

blocking: Returned UUID can differ from the transmitted UUID

This promises that capture_ai() returns the event UUID, but _enqueue() snapshots sent_uuid before invoking before_send. Because that supported callback can replace or remove msg["uuid"], the queued event can differ from the returned UUID, breaking the deduplication contract. Please normalize/generate the UUID after before_send, return the final queued UUID, and add regression coverage for callbacks that replace or remove it.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed!

@marandaneto
marandaneto requested a review from a teamAugust 12, 2026 12:53
Generated-By: PostHog Code
Task-Id: 4b5e5cda-81f1-41a2-8fcd-4f335d19217e
@carlos-marchal-ph
carlos-marchal-ph merged commit 178ef43 into mainAug 13, 2026
37 checks passed
@carlos-marchal-ph
carlos-marchal-ph deleted the feat(aio)/capture-ai-public-beta branch August 13, 2026 11:53
Sign up for freeto 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.

2 participants

@carlos-marchal-ph@marandaneto