Skip to content

Conversation

@kappa90
Copy link
Contributor

@kappa90 kappa90 commented Nov 20, 2025

Problem

Conversation that started this here

We need a way to store and manage artifacts created by the AI agents, such as visualizations and documents.

Changes

  • Created a new AgentArtifact model to store artifacts generated during conversations
  • Implemented a REST API for retrieving, listing, and deleting artifacts
  • Artifacts are automatically deleted when their parent conversation is deleted

How did you test this code?

Added tests

Copy link
Contributor Author

kappa90 commented Nov 20, 2025

@kappa90 kappa90 requested a review from a team November 20, 2025 15:32
@kappa90 kappa90 marked this pull request as ready for review November 20, 2025 15:32
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

7 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines 51 to 58
def destroy(self, request, *args, **kwargs):
instance = self.get_object()

if instance.conversation.user != request.user:
return Response(
{"error": "Cannot delete other users' artifacts"},
status=status.HTTP_403_FORBIDDEN,
)
Copy link
Contributor

Choose a reason for hiding this comment

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

style: redundant ownership check - safely_get_queryset already filters by conversation__user=self.request.user, so get_object() will return 404 if user doesn't own the artifact

Suggested change
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
if instance.conversation.user != request.user:
return Response(
{"error": "Cannot delete other users' artifacts"},
status=status.HTTP_403_FORBIDDEN,
)
def destroy(self, request, *args, **kwargs):
return super().destroy(request, *args, **kwargs)
Prompt To Fix With AI
This is a comment left during a code review.
Path: ee/api/agent_artifact.py
Line: 51:58

Comment:
**style:** redundant ownership check - `safely_get_queryset` already filters by `conversation__user=self.request.user`, so `get_object()` will return 404 if user doesn't own the artifact

```suggestion
    def destroy(self, request, *args, **kwargs):
        return super().destroy(request, *args, **kwargs)
```

How can I resolve this? If you propose a fix, please make it concise.

@kappa90 kappa90 force-pushed the 11-18-refactor_ph-ai_clean_up_scaffolding branch from bb5fddb to 5f3aefb Compare November 20, 2025 15:34
@kappa90 kappa90 force-pushed the 11-20-feat_ph-ai_agent_artifacts_api_endpoint branch from 049b2f5 to 7b4e4ac Compare November 20, 2025 15:35
@github-actions
Copy link
Contributor

github-actions bot commented Nov 20, 2025

🔍 Migration Risk Analysis

We've analyzed your migrations for potential risks.

Summary: 1 Safe | 0 Needs Review | 0 Blocked

✅ Safe

No contention risk, backwards compatible

ee.0031_agentartifact
  └─ #1 ✅ CreateModel
     Creating new table is safe
     model: AgentArtifact
  │
  └──> ℹ️  INFO:
       ℹ️  Skipped operations on newly created tables (empty tables
       don't cause lock contention).

Last updated: 2025-11-21 19:37 UTC (53c050f)

@kappa90 kappa90 force-pushed the 11-18-refactor_ph-ai_clean_up_scaffolding branch from 5f3aefb to f57a488 Compare November 20, 2025 15:56
@kappa90 kappa90 force-pushed the 11-20-feat_ph-ai_agent_artifacts_api_endpoint branch from 7b4e4ac to e6b941a Compare November 20, 2025 15:57
@kappa90 kappa90 force-pushed the 11-18-refactor_ph-ai_clean_up_scaffolding branch from f57a488 to c22ef9d Compare November 20, 2025 15:58
@kappa90 kappa90 force-pushed the 11-20-feat_ph-ai_agent_artifacts_api_endpoint branch 2 times, most recently from 1550750 to 9a0e58b Compare November 20, 2025 16:14
@kappa90 kappa90 force-pushed the 11-18-refactor_ph-ai_clean_up_scaffolding branch from c22ef9d to 8eb9a7d Compare November 20, 2025 16:14
@kappa90 kappa90 force-pushed the 11-20-feat_ph-ai_agent_artifacts_api_endpoint branch from 9a0e58b to c518e20 Compare November 20, 2025 16:17
@kappa90 kappa90 force-pushed the 11-18-refactor_ph-ai_clean_up_scaffolding branch 2 times, most recently from 12744ff to 8e15cf1 Compare November 20, 2025 16:37
@kappa90 kappa90 force-pushed the 11-20-feat_ph-ai_agent_artifacts_api_endpoint branch 2 times, most recently from 2f258be to b1a4dd3 Compare November 20, 2025 19:26
@kappa90 kappa90 force-pushed the 11-18-refactor_ph-ai_clean_up_scaffolding branch from 8e15cf1 to 2febab6 Compare November 20, 2025 19:27
Copy link
Contributor

@skoob13 skoob13 left a comment

Choose a reason for hiding this comment

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

Left comments mostly about the model. My suggestion is to remove the artifacts endpoint, as there is no use case for now. Also can we merge this PR to master? I'd need it too.

Comment on lines 214 to 229
def save(self, *args, **kwargs):
max_retries = 5
for attempt in range(max_retries):
try:
with transaction.atomic():
return super().save(*args, **kwargs)
except IntegrityError as e:
if "short_id" in str(e) and attempt < max_retries - 1:
self.short_id = generate_short_id_6()
else:
raise
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we move it to the logic rather than keep it on the model's level?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not sure, this will basically always have to be done, anytime we're creating the model.

class AgentArtifact(UUIDModel):
class Type(models.TextChoices):
VISUALIZATION = "visualization", "Visualization"
DOCUMENT = "document", "Document"
Copy link
Contributor

Choose a reason for hiding this comment

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

It's a bit ambiguous. I assume it's a notebook. But who knows?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No it can also be a generated (not-saved) insight, it's whatever the agent generates. I need visualizations to be artifacts so they can be reused within deep research, when adding them to the reports, without the agent having to rewrite the queries every single time (it can just reference the short_id)

Copy link
Contributor

Choose a reason for hiding this comment

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

So what is the document? Is it just some generic text?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's a notebook-like document, but TipTap-agnostic, I have the model in the next PR.

It can be something like:
- markdown block
- visualization
- markdown
- session replay video

This can be easily extended with runnable code blocks or whatever, I'm thinking about a Jupyter notebook final use case, which also works right now for research/session summaries. This is basically a document that we can more easily display in the frontend, without passing by the full Prosemirror text editor, which is super slow.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'll rephrase the question: For this enum type, is there only a single Pydantic schema, or are there multiple?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Aaaah ok, I thought you were saying that AgentArtifact​ is ambiguous, not the Document​ enum.

There would be only one Pydantic schema (the document), with sub-blocks for the different content elements.

I can rename it to notebook, just didn't want to collide with the existing Notebook model.

Copy link
Contributor

Choose a reason for hiding this comment

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

Got it, cool. Let's maybe rename it to the notebook? It doesn't collide since it's a member of an enum type. Just want to make sure the model is easy to understand.

def destroy(self, request, *args, **kwargs):
instance = self.get_object()

if instance.conversation.user != request.user:
Copy link
Contributor

Choose a reason for hiding this comment

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

We always scope by tenant, so I think it's fine to have deletion at the tenant level. This goes a bit to RBAC.

@kappa90 kappa90 force-pushed the 11-18-refactor_ph-ai_clean_up_scaffolding branch from 2febab6 to 81c7220 Compare November 21, 2025 15:11
@kappa90 kappa90 force-pushed the 11-20-feat_ph-ai_agent_artifacts_api_endpoint branch 2 times, most recently from 23c326b to b465263 Compare November 21, 2025 15:16
@kappa90 kappa90 force-pushed the 11-18-refactor_ph-ai_clean_up_scaffolding branch 2 times, most recently from 396ac44 to 7363a7c Compare November 21, 2025 15:38
@kappa90 kappa90 force-pushed the 11-20-feat_ph-ai_agent_artifacts_api_endpoint branch from 91a286e to 0f84b95 Compare November 21, 2025 16:12
@kappa90 kappa90 changed the title feat(ph-ai): agent artifacts API endpoint feat(ph-ai): agent artifacts model Nov 21, 2025
@kappa90 kappa90 force-pushed the 11-18-refactor_ph-ai_clean_up_scaffolding branch from d1cd8ab to f253c04 Compare November 21, 2025 16:23
@kappa90 kappa90 force-pushed the 11-20-feat_ph-ai_agent_artifacts_api_endpoint branch 3 times, most recently from 402dc8b to fc07aea Compare November 21, 2025 17:02
@kappa90 kappa90 force-pushed the 11-18-refactor_ph-ai_clean_up_scaffolding branch from f253c04 to 5a1c5f3 Compare November 21, 2025 17:02
@kappa90 kappa90 force-pushed the 11-20-feat_ph-ai_agent_artifacts_api_endpoint branch from fc07aea to 84da926 Compare November 21, 2025 17:21
@kappa90 kappa90 force-pushed the 11-18-refactor_ph-ai_clean_up_scaffolding branch from 5a1c5f3 to 2b377bf Compare November 21, 2025 17:22
@kappa90 kappa90 force-pushed the 11-20-feat_ph-ai_agent_artifacts_api_endpoint branch 2 times, most recently from 514a053 to e40b7da Compare November 21, 2025 17:23
@kappa90 kappa90 force-pushed the 11-18-refactor_ph-ai_clean_up_scaffolding branch 3 times, most recently from 70bf6e7 to 8f58081 Compare November 21, 2025 17:45
@kappa90 kappa90 force-pushed the 11-20-feat_ph-ai_agent_artifacts_api_endpoint branch 2 times, most recently from e096ffb to 3120090 Compare November 21, 2025 18:03
@kappa90 kappa90 force-pushed the 11-18-refactor_ph-ai_clean_up_scaffolding branch from 8f58081 to ccc4fe0 Compare November 21, 2025 18:03
@kappa90 kappa90 force-pushed the 11-20-feat_ph-ai_agent_artifacts_api_endpoint branch from 3120090 to 2101098 Compare November 21, 2025 18:17
@kappa90 kappa90 force-pushed the 11-18-refactor_ph-ai_clean_up_scaffolding branch from 7113cf6 to 0fc5130 Compare November 21, 2025 18:17
@kappa90 kappa90 force-pushed the 11-20-feat_ph-ai_agent_artifacts_api_endpoint branch from 2101098 to 3f2b627 Compare November 21, 2025 18:53
@kappa90 kappa90 force-pushed the 11-18-refactor_ph-ai_clean_up_scaffolding branch from 0fc5130 to 458276d Compare November 21, 2025 18:53
@kappa90 kappa90 changed the base branch from 11-18-refactor_ph-ai_clean_up_scaffolding to graphite-base/41830 November 21, 2025 19:15
@kappa90 kappa90 force-pushed the 11-20-feat_ph-ai_agent_artifacts_api_endpoint branch from 3f2b627 to 53c050f Compare November 21, 2025 19:16
@kappa90 kappa90 force-pushed the graphite-base/41830 branch from 458276d to 55edaab Compare November 21, 2025 19:16
@graphite-app graphite-app bot changed the base branch from graphite-base/41830 to master November 21, 2025 19:17
@graphite-app
Copy link
Contributor

graphite-app bot commented Nov 21, 2025

Merge activity

  • Nov 21, 7:17 PM UTC: Graphite rebased this pull request, because this pull request is set to merge when ready.
  • Nov 21, 7:49 PM UTC: @kappa90 merged this pull request with Graphite.

@kappa90 kappa90 merged commit 892a55c into master Nov 21, 2025
333 of 378 checks passed
@kappa90 kappa90 deleted the 11-20-feat_ph-ai_agent_artifacts_api_endpoint branch November 21, 2025 19:49
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.

3 participants