Artifacts
Artifacts are structured, interactive outputs that agents produce during conversations. Instead of returning plain text, an agent can produce a rich artifact — an email draft, a meeting invite, a CRM records table, a task, or a calendar view — that the user can review, edit, and act on directly in the chat interface.How artifacts work
When an agent produces an artifact, it creates a typed payload with two components:- Content — the structured data the UI renders (e.g., email fields, meeting details, table rows)
- State — lifecycle status driven by user actions (draft, sent, scheduled, confirmed, cancelled)
Artifact types
| Type | Description | Actions |
|---|---|---|
| Email draft | Structured email with to/cc/bcc, subject, body | Send, edit, discard |
| Meeting invite | Calendar event with attendees, time, agenda | Schedule via Google Calendar |
| Task | Action item with assignee, due date, priority | Create in task system |
| Scheduled task | Recurring or time-triggered agent task | Activate, pause, delete |
| Slack message | Formatted Slack message draft | Send to channel |
| Records table | CRM data table (accounts, contacts, opportunities) | Sort, filter, drill-in |
| Calendar | Inline calendar view | Navigate, click events |
| Plan | Multi-step execution plan | Review, modify steps |
API
List registered artifact types
panel or inline), and streaming support.
Get an artifact
List artifacts in a conversation
Update artifact state
When a user takes action on an artifact (sends an email, schedules a meeting):Edit artifact content
For inline editing (e.g., changing email subject before sending):Execute artifact actions
Summarizers and the caching layer
Every artifact type has a summarizer — a function that takes the full artifact content and produces a compact summary dict. This powers two critical features:LLM context efficiency
When tool results are large (CRM record sets, email threads, meeting lists), the full data would consume the entire context window. Instead, AgentFlow:- Caches the full result in a TTL-scoped result cache
- Summarizes it into a compact dict (total count, field names, 3-row preview)
- Returns the summary to the LLM conversation, with a
cache_idreference - The full data remains available through the conversation-scoped cached-results API while the entry is valid
Tool-result cache registration
Tools that produce cacheable structured output register their artifact type and cache summarizer together inartifacts/<type>/ARTIFACT.py. The @artifact(...) decorator registers the artifact type and preview summarizer; register_cached_tool(...) wires a tool’s result cache to reuse that same summarizer.
- Registers a cache configuration (summarizer function, TTL, cache threshold)
- Registers a matching artifact type (so the UI can render the data as a panel)
- Links the tool result to both the cache and the artifact system
dict -> dict interface — it takes the full result and returns the compact summary:
Built-in summarizers
| Tool category | What’s summarized | TTL |
|---|---|---|
| CRM records | Total count, field names, 3-row preview | 30 min |
| Emails | Total count, field names, 3-row preview | 1 hour |
| Meetings | Total count, field names, 3-row preview | 1 hour |
| Tasks | Total count, field names, 3-row preview | 30 min |
| Slack messages | Total count, has_more flag, 3-message preview | 10 min |
| Record fields/views | Field names, object type, counts | 24 hours |
Agent context injection
Agents automatically receive compact summaries of existing artifacts in the conversation as<system_events> parts. This means the agent knows what drafts are pending, what’s been sent, and what actions the user has taken — enabling natural follow-up interactions like “actually, change the meeting to 3pm” or “add the quarterly numbers to that email”.
When a user takes an action (sends an email, schedules a meeting), an <artifact_action> system event is persisted so subsequent agent turns are aware of what changed.
Artifact feedback loop
Artifacts aren’t static outputs — they participate in a closed feedback loop that enables multi-turn refinement. This is the mechanism that makes “change the subject line” or “actually, schedule it for 3pm” work naturally across conversation turns.How context parts accumulate
Each artifact interaction creates persistentsystem_event parts in the conversation:
| Trigger | Context type | What it contains | Visible in timeline |
|---|---|---|---|
| Agent streams an artifact | <artifact_summary> | Compact summarizer output (to, subject, body preview) | No (hidden) |
| User sends/schedules/creates | <artifact_action> | Action name + summary of what changed | Yes |
| User edits content inline | <artifact_action> | Fields that were modified | Yes |
| User clicks/interacts | <artifact_action> | Interaction data from the UI | Yes |
system_event conversation parts with a stable part_id per artifact per action. On the next agent turn, the history rebuilder includes them as context — so the agent knows the email was sent, the meeting was scheduled, or the user edited the task description.
Revision support
Artifacts can be revised across turns. When the agent targets an existing artifact ID in its structured artifact payload, the middleware updates the existing artifact instead of creating a new one. This enables:- “Change the subject line” -> agent emits an updated
draft_emailpayload forart_001 - “Add Sarah to the invite” -> agent emits an updated
draft_meeting_invitepayload forart_002 - The UI reflects the update in-place without creating duplicate cards

