Skip to content

feat: annotation queue testset export#4261

Open
ashrafchowdury wants to merge 14 commits intomainfrom
feat/frontend-annotation-queue-testset
Open

feat: annotation queue testset export#4261
ashrafchowdury wants to merge 14 commits intomainfrom
feat/frontend-annotation-queue-testset

Conversation

@ashrafchowdury
Copy link
Copy Markdown
Contributor

No description provided.

claude and others added 9 commits May 4, 2026 14:56
Adds PRD, RFC, and README to docs/designs/testset-annotation-queue/.

The design covers:
- Per-scenario "Add to Testset" button in the annotate tab
- "Done with queue" screen supporting both trace and testcase queues
- All-annotations tab with row selection and upgraded commit modal
- New AddToTestsetModal component with EntityPicker integration
- Controller actions for addScenariosToTestset (trace + testcase paths)
- Default target testset heuristics and last-used persistence

https://claude.ai/code/session_01B2uQKidAr1KJ4CR9sroY2H
Key corrections:
- Replace new AddToTestsetModal with EntityCommitModal + renderModeContent
- Replace useState for selected testset with pendingTestsetSelectionAtom
  in annotationSessionController — survives re-renders and can be read
  imperatively by addScenariosToTestset without closure capture
- selectedScenarioIdsAtom for row selection (also atom, not useState)
- openAddToTestsetModal seeds pendingTestsetSelectionAtom from default
- addScenariosToTestset reads target testset from atom, not payload
- Add state atom summary table documenting all atom lifecycles

https://claude.ai/code/session_01B2uQKidAr1KJ4CR9sroY2H
Inputs (agData.inputs) spread into N columns — one per input key.
Outputs (agData.outputs) always map to a single "output" column
regardless of value shape, matching extractOutputs() behaviour in
trace/utils/selectors.ts which treats outputs as a leaf.
Annotation values add one column per evaluator slug.
…n reset

1. Trace annotation resolution: use scenarioAnnotationsAtomFamily(scenarioId)
   not a raw query by traceId. The atom handles step-based resolution to avoid
   cross-queue bleed (as documented in the controller).

2. Scope label when scope="all": addToTestsetScenarioIds() is empty for the
   "all" case — read actual count from scenarioIds() instead of falling back
   to the "all" string.

3. Row selection reset: addScenariosToTestset clears selectedScenarioIdsAtom
   after a successful export so stale selections don't persist.
@vercel
Copy link
Copy Markdown

vercel Bot commented May 5, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agenta-documentation Ready Ready Preview, Comment May 5, 2026 2:05pm

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 5, 2026

📝 Walkthrough

Summary by CodeRabbit

Release Notes

  • New Features

    • Added "Add to Testset" functionality to create testsets directly from annotation sessions with per-scenario, bulk, and queue-wide export options.
    • Introduced testset selection modal allowing users to choose existing testsets or create new ones during annotation export.
    • Added persistent per-project default target testset preference to streamline repeated exports.
  • Improvements

    • Enhanced annotation interface with improved button placement and workflow efficiency.

Walkthrough

This PR adds a design and implementation for creating testsets directly from annotation queues. It includes design documentation (PRD, RFC, README) outlining requirements and architecture, new controller atoms/actions for managing modal state and background export jobs, UI components for "Add to Testset" buttons across annotation views, testset row-builder utilities for traces and testcases, and entity UI enhancements (modal, picker) to support testset selection and creation during export.

Changes

Design Documentation

Layer / File(s) Summary
PRD & Scope Definition
docs/designs/testset-annotation-queue/PRD.md, docs/designs/testset-annotation-queue/README.md
Problem statement, goals, user stories, and functional requirements (FR1–FR7) for exporting annotation queue results into testsets with scope control, default heuristics, and data-mapping rules. README refines scope, lists in-scope/out-of-scope items, and enumerates open design questions.
Technical Architecture
docs/designs/testset-annotation-queue/RFC.md
Frontend-only implementation using reusable EntityCommitModal and EntityPicker, new annotationSessionController atoms for modal/job state, row-builder functions, trace/testcase data mapping, UI integration points, and verification plan.

Add-to-Testset Feature Implementation

Layer / File(s) Summary
Type Definitions
web/packages/agenta-annotation/src/state/types.ts, web/packages/agenta-annotation/src/state/controllers/annotationSessionController.ts
AnnotationDataColumnDef gains optional outputColumns for expanded evaluator child columns. New exported types: AddToTestsetScope, AddToTestsetExportJob with status/progress tracking.
Testset API Extensions
web/packages/agenta-entities/src/testset/api/api.ts, web/packages/agenta-entities/src/testset/api/index.ts, web/packages/agenta-entities/src/testset/index.ts
fetchRevisionWithTestcases now accepts optional testcaseLimit. New fetchLatestRevisionWithTestcases exported for retrieving latest revision with testcases, supporting windowing limits.
Row Building Utilities
web/packages/agenta-annotation/src/state/testsetSync.ts
New exported row builders: buildTraceTestsetRows (expands trace inputs, stores outputs as leaf column, flattens evaluator annotations) and buildTestcaseExportRows (exports to selected testset with annotation output flattening). Shared helpers for annotation output normalization, slug mapping, and data merging.
Controller State & Logic
web/packages/agenta-annotation/src/state/controllers/annotationSessionController.ts
New atoms for modal open/close, export scope, scenario selection, pending testset, and background job status. New actions: openAddToTestsetModal, closeAddToTestsetModal, setPendingTestsetSelection, setSelectedScenarioIds, addScenariosToTestset. Core async flow: resolve export scope/scenarios, build rows, create/patch testset, track job progress, invalidate queries, handle errors. canAddToTestset selector determines capability per queue type.
Controller Exports
web/packages/agenta-annotation/src/state/controllers/index.ts, web/packages/agenta-annotation/src/index.ts
Type re-exports propagate AddToTestsetScope and AddToTestsetExportJob through controller and state module public APIs.
Modal & Picker Infrastructure
web/packages/agenta-entity-ui/src/modals/commit/components/EntityCommitContent.tsx, web/packages/agenta-entity-ui/src/modals/commit/components/EntityCommitModal.tsx, web/packages/agenta-entity-ui/src/modals/commit/state.ts, web/packages/agenta-entity-ui/src/selection/components/UnifiedEntityPicker/types.ts, web/packages/agenta-entity-ui/src/selection/components/UnifiedEntityPicker/variants/CascadingVariant.tsx, web/packages/agenta-entity-ui/src/selection/hooks/modes/useCascadingMode.ts
Reordered EntityCommitContent to render warning/mode selector before entity-name editing. EntityCommitModal no longer resets state after onSubmit success (relies on afterClose). Added onDeselect callback to CascadingVariant and useCascadingMode to support clearing testset selection.
Annotation Session Integration
web/packages/agenta-annotation-ui/src/components/AnnotationSession/index.tsx
Wires new EntityCommitModal with testset adapter (ADD_TO_TESTSET_TARGET_ADAPTER), commit modes (create/select), handlers for testset selection/deselection, and async submit via addScenariosToTestset. Adds success-toast logic. Removes old testset sync handler. Simplifies header to show queue name only.
UI Component Updates
web/packages/agenta-annotation-ui/src/components/AnnotationSession/FocusView.tsx, web/packages/agenta-annotation-ui/src/components/AnnotationSession/ScenarioListView.tsx, web/packages/agenta-annotation-ui/src/components/AnnotationSession/SessionNavigation.tsx
FocusView AllCaughtUp screen replaces old sync flow with new "Add to Testset" button for all queue types (primary for testcases). Removes onSyncToTestset/isSyncing props. ScenarioListView adds row-selection checkboxes, derives expanded annotation child columns, updates export column state/cell value resolution for annotation children, and replaces sync button with queue-kind-agnostic "Add to Testset" button. SessionNavigation adds per-scenario "Add to Testset" button in the footer.

Sequence Diagram

sequenceDiagram
    participant User
    participant AnnotationSession
    participant EntityCommitModal
    participant EntityPicker
    participant annotationSessionController
    participant TestsetAPI
    participant QueryClient

    User->>AnnotationSession: Click "Add to Testset"
    AnnotationSession->>annotationSessionController: openAddToTestsetModal({scope, scenarioIds})
    annotationSessionController->>EntityCommitModal: Set isAddToTestsetModalOpen = true
    EntityCommitModal->>User: Display modal with commit mode selector

    alt Mode = "select"
        User->>EntityCommitModal: Choose target testset
        EntityCommitModal->>EntityPicker: Load testsets list
        EntityPicker->>TestsetAPI: Fetch testsets
        TestsetAPI-->>EntityPicker: Return testsets
        EntityPicker-->>User: Display testset options
        User->>EntityCommitModal: Select testset
        EntityCommitModal->>annotationSessionController: setPendingTestsetSelection(testsetId)
    else Mode = "create"
        User->>EntityCommitModal: Enter new testset name
        EntityCommitModal->>annotationSessionController: setPendingTestsetSelection({name})
    end

    User->>EntityCommitModal: Click "Confirm"
    EntityCommitModal->>annotationSessionController: addScenariosToTestset(scope, mode, fields)
    annotationSessionController->>annotationSessionController: Resolve scope (single/selected/all/complete)
    annotationSessionController->>annotationSessionController: Build export rows from scenarios
    
    alt Target testset exists
        annotationSessionController->>TestsetAPI: patchRevision(testsetId, {addedColumns, addedRows})
    else Create new testset
        annotationSessionController->>TestsetAPI: createTestset({name, rows})
    end
    
    TestsetAPI-->>annotationSessionController: Success response
    annotationSessionController->>QueryClient: Invalidate testset queries
    annotationSessionController->>annotationSessionController: Update job status to success
    EntityCommitModal->>AnnotationSession: Close modal
    AnnotationSession->>User: Display success toast
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly Related Issues

  • Prepare PRD and UX for annotation queue flow #4247 — This PR directly addresses the requirement to add a PRD and implement unified UX for creating/updating testsets from annotation queues, covering per-scenario and bulk export flows with modal-based testset selection.
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 60.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive No pull request description was provided by the author, making it impossible to verify relevance to the changeset. Add a meaningful pull request description that explains the purpose, scope, and key changes of this feature implementation.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: annotation queue testset export' clearly describes the main feature addition: enabling export of annotation queue data to testsets.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/frontend-annotation-queue-testset

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
docs/designs/testset-annotation-queue/PRD.md (1)

42-48: 💤 Low value

Add blank lines around tables for markdown compliance.

The tables in this document are missing surrounding blank lines, which causes markdownlint warnings. This affects tables at lines 42, 89, 107, and 118.

📝 Example fix for the competitive reference table
 ## Competitive Reference
 
 ### LangSmith
+
 | Capability | Supported |
 |------------|-----------|
 | Create or extend a testset from both test cases and traces | Yes |
 | Add a single scenario to a testset | Yes |
 | Add to a testset from the focused/annotate tab | Yes |
 | Select table rows and add them to a testset | Yes |
+
 LangSmith supports all four capabilities; Agenta currently supports none of them in full.
docs/designs/testset-annotation-queue/RFC.md (1)

18-57: 💤 Low value

Add language specifiers to fenced code blocks.

Several code blocks in this RFC lack language specifiers, which affects syntax highlighting and readability. The architecture diagram at line 18 and examples at lines 244, 361, 366, 385, 391, 485, 500, 517 should specify a language (use text or plaintext for ASCII diagrams).

📝 Example fix for ASCII diagram
-```
+```text
 User action (button click)
         │
         ▼

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 22636d88-f5f8-408b-a088-51bb814f81e5

📥 Commits

Reviewing files that changed from the base of the PR and between bd447c0 and ee683a1.

📒 Files selected for processing (11)
  • docs/designs/testset-annotation-queue/PRD.md
  • docs/designs/testset-annotation-queue/README.md
  • docs/designs/testset-annotation-queue/RFC.md
  • web/packages/agenta-annotation-ui/src/components/AnnotationSession/FocusView.tsx
  • web/packages/agenta-annotation-ui/src/components/AnnotationSession/ScenarioListView.tsx
  • web/packages/agenta-annotation-ui/src/components/AnnotationSession/SessionNavigation.tsx
  • web/packages/agenta-annotation-ui/src/components/AnnotationSession/index.tsx
  • web/packages/agenta-entity-ui/src/modals/commit/components/EntityCommitContent.tsx
  • web/packages/agenta-entity-ui/src/selection/components/UnifiedEntityPicker/types.ts
  • web/packages/agenta-entity-ui/src/selection/components/UnifiedEntityPicker/variants/CascadingVariant.tsx
  • web/packages/agenta-entity-ui/src/selection/hooks/modes/useCascadingMode.ts

@ashrafchowdury ashrafchowdury marked this pull request as ready for review May 5, 2026 12:35
@dosubot dosubot Bot added size:XXL This PR changes 1000+ lines, ignoring generated files. feature Frontend labels May 5, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
web/packages/agenta-annotation-ui/src/components/AnnotationSession/ScenarioListView.tsx (1)

552-569: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Keep the testcase fallback key separate from the metric path.

AnnotationOutputKeyCell passes outputKey into useAnnotationCellFallback(), and after Line 912 that value is often the full mapped path (attributes.ag.data.outputs.score, etc.). The fallback hook indexes the testcase container object by that same string, so grouped annotation cells now miss synced testcase values and render until an annotation exists.

Possible fix
 const AnnotationOutputKeyCell = memo(function AnnotationOutputKeyCell({
     scenarioId,
     def,
     outputKey,
+    fallbackOutputKey,
     fallbackDataKey,
 }: {
     scenarioId: string
     def: AnnotationColumnDef
     outputKey: string
+    fallbackOutputKey?: string
     fallbackDataKey?: string | null
 }) {
     const runId = useAtomValue(annotationSessionController.selectors.activeRunId()) ?? undefined
     const PopoverWrapper = useMetricPopoverWrapper()
     const {fallbackValue, isPending} = useAnnotationCellFallback(
         scenarioId,
         fallbackDataKey,
-        outputKey,
+        fallbackOutputKey ?? outputKey,
     )
                         render: (_value: unknown, record: ScenarioTableRow) => (
                             <AnnotationOutputKeyCell
                                 scenarioId={record.scenarioId}
                                 def={outputColumn.annotationDef}
                                 outputKey={outputColumn.annotationDef.path ?? outputColumn.title}
+                                fallbackOutputKey={outputColumn.title}
                                 fallbackDataKey={def.fallbackDataKey}
                             />
                         ),

Also applies to: 899-913


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e691f741-e404-4527-b6c9-1dbc7e659952

📥 Commits

Reviewing files that changed from the base of the PR and between ee683a1 and 7bea0bc.

📒 Files selected for processing (12)
  • web/packages/agenta-annotation-ui/src/components/AnnotationSession/ScenarioListView.tsx
  • web/packages/agenta-annotation/src/index.ts
  • web/packages/agenta-annotation/src/state/controllers/annotationSessionController.ts
  • web/packages/agenta-annotation/src/state/controllers/index.ts
  • web/packages/agenta-annotation/src/state/index.ts
  • web/packages/agenta-annotation/src/state/testsetSync.ts
  • web/packages/agenta-annotation/src/state/types.ts
  • web/packages/agenta-entities/src/testset/api/api.ts
  • web/packages/agenta-entities/src/testset/api/index.ts
  • web/packages/agenta-entities/src/testset/index.ts
  • web/packages/agenta-entity-ui/src/modals/commit/components/EntityCommitModal.tsx
  • web/packages/agenta-entity-ui/src/modals/commit/state.ts
💤 Files with no reviewable changes (2)
  • web/packages/agenta-entity-ui/src/modals/commit/state.ts
  • web/packages/agenta-entity-ui/src/modals/commit/components/EntityCommitModal.tsx
✅ Files skipped from review due to trivial changes (1)
  • web/packages/agenta-annotation/src/state/index.ts

Comment on lines +2339 to +2365
async function waitForStoreAtomValue<T>(
atomToWatch: unknown,
isReady: (value: T) => boolean,
timeoutMs = 5000,
): Promise<T> {
const store = getStore()
const atomRef = atomToWatch as unknown as Parameters<typeof store.get>[0]
const subRef = atomToWatch as unknown as Parameters<typeof store.sub>[0]
const current = store.get(atomRef) as T
if (isReady(current)) return current

return await new Promise<T>((resolve) => {
const timeout = setTimeout(() => {
unsubscribe()
resolve(store.get(atomRef) as T)
}, timeoutMs)

const unsubscribe = store.sub(subRef, () => {
const next = store.get(atomRef) as T
if (isReady(next)) {
clearTimeout(timeout)
unsubscribe()
resolve(next)
}
})
})
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fail the export when annotation queries never settle.

Unlike the trace query, the waits on Lines 2633-2644 never validate the returned state. If scenario steps or annotations are still pending — or already errored — Lines 2646-2653 still build the export row from the current store value, which collapses to empty annotations. That turns a slow/failing fetch into a successful export with missing evaluator outputs.

Also applies to: 2633-2653

Comment on lines +2548 to +2561
async function fetchLatestRevisionWithRows(params: {
projectId: string
testsetId: string
}): Promise<LatestRevisionWithRows> {
const latestRevision = await fetchLatestRevisionWithTestcases({
projectId: params.projectId,
testsetId: params.testsetId,
testcaseLimit: 1,
})
if (!latestRevision?.id) {
throw new Error("The latest revision for the selected testset could not be resolved.")
}

return latestRevision as LatestRevisionWithRows
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Don't infer the target schema from a single testcase row.

This branch builds existingColumns from fetchLatestRevisionWithRows(), but that helper requests testcaseLimit: 1. If the sampled row does not contain every leaf path already present in the target testset, remapRowsToExistingLeafColumns() can miss valid existing columns and patchRevision() will add duplicate/misaligned paths instead of reusing the current schema.

Also applies to: 2824-2830

Comment on lines +206 to +227
function applyAnnotationOutputEntries(
data: Record<string, unknown>,
entries: {columnKey: string; outputs: Record<string, unknown>}[],
): string[] {
const evaluatorColumnKeys: string[] = []

for (const entry of entries) {
const existingValue = data[entry.columnKey]
data[entry.columnKey] = {
...(isPlainRecord(existingValue) ? existingValue : {}),
...entry.outputs,
}

for (const [fieldKey, fieldValue] of Object.entries(entry.outputs)) {
if (fieldValue !== undefined) {
evaluatorColumnKeys.push(`${entry.columnKey}.${fieldKey}`)
}
}
}

return evaluatorColumnKeys
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Flatten nested annotation outputs before recording evaluatorColumnKeys.

Line 219 only appends ${entry.columnKey}.${fieldKey} for first-level properties. If an evaluator emits structured output like {rubric: {score: 1}}, the sync preview will declare judge.rubric as the column while the row data still contains deeper leaf paths. That leaves nested annotation fields undeclared/remapped incorrectly during testcase sync.

}: RevisionDetailParams): Promise<Revision | null> {
testcaseLimit,
}: RevisionDetailParams & {testcaseLimit?: number}): Promise<Revision | null> {
if (testcaseLimit) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use explicit undefined checks for testcaseLimit and validate bounds.

Line 62 and Line 108 use truthy checks. That treats 0 as “not provided” and can still allow invalid numeric values through, leading to unintended full testcase fetches or bad API requests.

Suggested patch
 export async function fetchRevisionWithTestcases({
     id,
     projectId,
     testcaseLimit,
 }: RevisionDetailParams & {testcaseLimit?: number}): Promise<Revision | null> {
-    if (testcaseLimit) {
+    const hasTestcaseLimit = testcaseLimit !== undefined && testcaseLimit !== null
+    if (hasTestcaseLimit) {
+        if (!Number.isInteger(testcaseLimit) || testcaseLimit < 0) {
+            throw new Error(
+                "[fetchRevisionWithTestcases] testcaseLimit must be a non-negative integer",
+            )
+        }
         const response = await axios.post(
             `${getAgentaApiUrl()}/testsets/revisions/retrieve`,
             {
                 testset_revision_ref: {id},
                 include_testcases: true,
                 windowing: {limit: testcaseLimit},
             },
             {params: {project_id: projectId}},
         )
@@
 export async function fetchLatestRevisionWithTestcases({
     projectId,
     testsetId,
     testcaseLimit,
 }: RevisionListParams & {testcaseLimit?: number}): Promise<Revision | null> {
+    const hasTestcaseLimit = testcaseLimit !== undefined && testcaseLimit !== null
+    if (hasTestcaseLimit && (!Number.isInteger(testcaseLimit) || testcaseLimit < 0)) {
+        throw new Error(
+            "[fetchLatestRevisionWithTestcases] testcaseLimit must be a non-negative integer",
+        )
+    }
     const response = await axios.post(
         `${getAgentaApiUrl()}/testsets/revisions/retrieve`,
         {
             testset_ref: {id: testsetId},
             include_testcases: true,
-            ...(testcaseLimit ? {windowing: {limit: testcaseLimit}} : {}),
+            ...(hasTestcaseLimit ? {windowing: {limit: testcaseLimit}} : {}),
         },
         {params: {project_id: projectId}},
     )

Also applies to: 108-108

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 5, 2026

Railway Preview Environment

Preview URL https://gateway-production-eac2.up.railway.app/w
Project agenta-oss-pr-4261
Image tag pr-4261-4d1050a
Status Deployed
Railway logs Open logs
Workflow logs View workflow run
Updated at 2026-05-05T14:11:34.299Z

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature Frontend size:XXL This PR changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants