feat(ai): add Prompts.get_all to fetch all prompts at a label - #938
Conversation
posthog-python Compliance ReportDate: 2026-09-10 13:32:34 UTC ✅ All Tests Passed!111/111 tests passed Capture_V1 Tests✅ 94/94 tests passed View Details
Feature_Flags Tests✅ 17/17 tests passed View Details
|
PR overviewAll previously flagged issues have been addressed. No open security concerns remain on this pull request. Security reviewNo open security issues remain on this pull request. Fixed/addressed: 1 · PR risk: 0/10 |
Prompt To Fix All With AI### Issue 1
posthog/ai/prompts.py:639-646
**Pagination returns incomplete results**
When a label spans more than 100 pages, this branch stops pagination and returns the accumulated prompts as a successful result. Callers therefore receive an incomplete dictionary and only a partially warmed cache even though `get_all` promises to fetch every prompt. The method should fail explicitly when it reaches the safety limit instead of presenting truncated data as complete.
### Issue 2
posthog/ai/prompts.py:408-412
**Compatibility failure skips telemetry**
The “none resolve label” exception is raised outside the block that calls `_maybe_capture_error`. Users who enable prompt error capture therefore receive telemetry for HTTP and parsing failures but not for this compatibility failure, making an important production misconfiguration harder to diagnose.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Reviews (1): Last reviewed commit: "feat(ai): add Prompts.get_all to fetch a..." | Re-trigger Greptile |
| if pages >= _MAX_PROMPT_LIST_PAGES: | ||
| log.warning( | ||
| "[PostHog Prompts] Stopped following pagination for %s after %d pages. " | ||
| "The result may be incomplete.", | ||
| reference, | ||
| pages, | ||
| ) | ||
| break |
There was a problem hiding this comment.
Pagination returns incomplete results
When a label spans more than 100 pages, this branch stops pagination and returns the accumulated prompts as a successful result. Callers therefore receive an incomplete dictionary and only a partially warmed cache even though get_all promises to fetch every prompt. The method should fail explicitly when it reaches the safety limit instead of presenting truncated data as complete.
Knowledge Base Used: AI observability
Prompt To Fix With AI
This is a comment left during a code review.
Path: posthog/ai/prompts.py
Line: 639-646
Comment:
**Pagination returns incomplete results**
When a label spans more than 100 pages, this branch stops pagination and returns the accumulated prompts as a successful result. Callers therefore receive an incomplete dictionary and only a partially warmed cache even though `get_all` promises to fetch every prompt. The method should fail explicitly when it reaches the safety limit instead of presenting truncated data as complete.
**Knowledge Base Used:** [AI observability](https://app.greptile.com/posthog-org-19734/-/custom-context/knowledge-base/posthog/posthog-python/-/docs/ai-observability.md)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| raise Exception( | ||
| f'[PostHog Prompts] The server returned prompts, but none resolve label "{label}". ' | ||
| "It may not support fetching prompts by label on the list endpoint yet. " | ||
| "Upgrade PostHog, or fetch prompts one by one with get()." | ||
| ) |
There was a problem hiding this comment.
Compatibility failure skips telemetry
The “none resolve label” exception is raised outside the block that calls _maybe_capture_error. Users who enable prompt error capture therefore receive telemetry for HTTP and parsing failures but not for this compatibility failure, making an important production misconfiguration harder to diagnose.
Knowledge Base Used: AI observability
Prompt To Fix With AI
This is a comment left during a code review.
Path: posthog/ai/prompts.py
Line: 408-412
Comment:
**Compatibility failure skips telemetry**
The “none resolve label” exception is raised outside the block that calls `_maybe_capture_error`. Users who enable prompt error capture therefore receive telemetry for HTTP and parsing failures but not for this compatibility failure, making an important production misconfiguration harder to diagnose.
**Knowledge Base Used:** [AI observability](https://app.greptile.com/posthog-org-19734/-/custom-context/knowledge-base/posthog/posthog-python/-/docs/ai-observability.md)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.|
found the same issues as the bots above |
|
No atomic snapshot guarantee: labels can move during pagination; the SDK currently skips mismatched rows which is ok i guess? |
|
@marandaneto For Prompt Management, Juraj now has more context than AIO. We'll still review it if needed, but Juraj holds the context and reasoning behind the changes. So if the SDK code looks good to your team, it's good with us! |
sorry my bad, my comment was supposed to be in the API PR :D |
marandaneto
left a comment
There was a problem hiding this comment.
approving to unblock but see comments
7c53e57 to
48ee3e7
Compare
|
Thanks @marandaneto! Yes I expect a label moving during pagination to be rare. The skipped row will log a warning and gets picked up on the next fetch, and if nothing resolves the label we raise an error rather than caching wrong versions. |
💡 Motivation and Context
What it does:
prompts.get_all(label="production")fetches every prompt at that label in one call, following pagination, and returns a dict of name toPromptResult.prompts.get(name, label="production")calls are cache hits. One call per cache cycle instead of one per prompt.labelparam on the list endpoint and return latest versions. Each row is checked against itsall_labelsfield; if nothing resolves the label, the call raises a clear error instead of caching wrong versions.💚 How did you test it?
New unit tests in
test_prompts.py:get()makes no request)Also ran ruff, mypy (baseline clean), the full prompts test file, and the public API snapshot check.
📝 Checklist
If releasing new changes
.sampo/changesets/(written by hand, same format assampo add)🤖 Agent context
Autonomy: Human-driven (agent-assisted)
get_allalways fetches (no cache read) so one call refreshes everything, like a feature flag poller. Rejected returning partial results when no row resolves the label, because that silently serves wrong versions.