PXI Approval Flow#
The PXI approval flow is the accept/reject pending-diff interaction pattern that gates all write operations in the PXI (Phoenix Agent UI) tool system behind explicit user confirmation. Every tool that mutates state β editing prompts, modifying tool definitions, managing datasets, creating annotation configs β stages a diff for the user to review before any change is applied.
Approval behavior is controlled by the user's edit_permission setting:
manualβ shows an inline approval card with Accept/Reject buttonsbypassβ applies changes immediately; agent receivesauto-approvedstatus
The pattern was introduced for playground prompt editing , then extended to prompt tool writes , dataset management , and annotation configs .
Lifecycle#
All approval-gated tools share the same five-step lifecycle :
Propose β Display β [Accept | Reject | Cancel]
- Propose β Tool stages a pending entry (diff preview, summary grid, etc.) in the Zustand
agentStoreslice keyed bytoolCallId. Fail-fast validation runs here; invalid batches never register a pending diff . - Display β UI renders an approval card (e.g.,
WritePromptToolsToolDetails,DatasetWriteApprovalCard). Cards are editable before commit β users can refine the proposal before accepting . - Accept β Commit callback re-validates the
expectedRevisiontoken against live store state. If the revision has drifted, a stale error is returned and nothing is applied . - Reject β Pending entry is cleared, playground/store state is unchanged, agent receives
rejectedoutput status . - Cancel β If the owning editor unmounts mid-review (user navigates away), a cancellation error is emitted to the agent rather than leaving the chat stuck .
Pending state is stored per-tool in agentStore.ts (e.g., pendingPromptEdits, pendingPromptToolWritesByToolCallId, pendingDatasetWritesByToolCallId), allowing multiple concurrent proposals to coexist and be individually resolved .
Diffs are rendered in display format β the exact format the user would edit in the JSONToolEditor or dataset form β so the user sees precisely what will change .
Agent Behavior After Rejection#
Tool instruction templates (e.g., WRITE_PROMPT_TOOLS_TOOL_INSTRUCTIONS.xml.j2) explicitly direct agent behavior for each outcome:
| Output status | Required agent behavior |
|---|---|
accepted | Changes applied; proceed |
auto-approved | Changes applied via bypass; proceed |
rejected | Do not retry the same batch. Ask the user what they'd like changed |
| Stale/drift error on accept | Re-read the current state and recompute the proposal before trying again |
Key rules enforced by the instructions:
- Never assume success until the output status is confirmed
- Rejected batches are discarded entirely β the prior batch cannot be re-submitted; the agent must start from a fresh read
- Read before write β tools like
edit_prompt_instancerequire callingread_prompt_instancefirst to capture theexpectedRevision - Vendor/passthrough tools are read-only β tools with
kind: "raw"(e.g.,web_search) cannot be created or edited via PXI, only deleted
Covered Tools & Source Pointers#
Approval-Gated Tools#
| Domain | Tools | PR |
|---|---|---|
| Playground prompts | read_prompt_instance, clone_prompt_instance, edit_prompt_instance | |
| Prompt tools (batch) | write_prompt_tools (atomic create/update/delete) | |
| Datasets | create_dataset, patch_dataset, delete_dataset, examples/labels/splits ops (~23 tools) | |
| Annotation configs | create_annotation_config, update_annotation_config | |
| Span notes | write_span_note (no approval β internal tool, writes directly) |
Key Source Files#
Frontend (TypeScript)
- Shared approval infrastructure:
app/src/agent/shared/pendingApproval/ - Agent store slices:
app/src/store/agentStore.ts - Playground prompt tools:
app/src/agent/tools/playgroundPrompt/ - Prompt tools write:
app/src/agent/tools/playgroundPromptTools/βpendingPromptToolWrite.ts,diffSummary.ts,clientActions.ts - Dataset tools:
app/src/agent/tools/{listDatasets,createDataset,datasetEdit,...}/ - Annotation config tools:
app/src/agent/tools/annotationConfig/
Backend (Python)
- Dataset capability tools:
src/phoenix/server/agents/capabilities/tools/external/ - Annotation config tools:
src/phoenix/server/agents/capabilities/tools/external/{create,update}_annotation_config.py - Span note internal tool:
src/phoenix/server/agents/capabilities/tools/internal/write_span_note.py - Agent instructions template:
src/phoenix/server/agents/prompts/tools/WRITE_PROMPT_TOOLS_TOOL_INSTRUCTIONS.xml.j2 - Playground chat tools:
src/phoenix/server/agents/chat_v2/tools/{read_prompt,clone_prompt_instance,edit_prompt}.py - Span coding skill:
src/phoenix/server/agents/skills/span_coding.py
Tool State UI Indicators#
The terminal UI (ToolStateIndicator) reflects approval state visually :
| State | Glyph | Meaning |
|---|---|---|
approval-requested | ? (yellow) | Waiting for user Accept/Reject |
approval-responded | spinner (yellow) | User responded; applying |
output-available | β (green) | Accepted & committed |
output-denied | β (dimmed) | Rejected |