Skip to content

[Hackathon] feat: Custom Operator Builder — Create Reusable Operators from Code#5108

Closed
EmilySun621 wants to merge 2 commits into
apache:mainfrom
EmilySun621:hackathon/custom-operators
Closed

[Hackathon] feat: Custom Operator Builder — Create Reusable Operators from Code#5108
EmilySun621 wants to merge 2 commits into
apache:mainfrom
EmilySun621:hackathon/custom-operators

Conversation

@EmilySun621
Copy link
Copy Markdown

@EmilySun621 EmilySun621 commented May 16, 2026

TL;DR: Write Python code once, save it as a real operator that appears in the drag-and-drop panel alongside built-in ones. Reusable, configurable, shareable — zero engine changes.

⚠️ Still under testing


😤 The Problem

A lab has Python functions they use in every project — a BMI calculator, an outlier remover, a custom normalization method. Every new workflow means someone opens a Python UDF and re-types the same code. If someone improves the function, the other workflows don't get the update.

No library. No reuse. No sharing. Just copy-paste across workflows.


✨ What We Built

🧩 Custom Operator Builder

Write Python code → save it as a named operator → drag and drop it in any workflow, just like a built-in one.


📋 My Operators Page

New sidebar entry under "Your Work":

Feature Details
🗂️ Operator grid Saved operators with icon, name, description, category
Create "+ Create Operator" button
✏️ Manage Edit, duplicate, delete existing operators

🖥️ Full-Page Operator Editor

Split-screen IDE-like experience:

Left panel (40%) — Configuration:

Setting Details
🏷️ Identity Name, description, icon picker (10 presets)
📂 Category Default "My Operators" or create custom categories
🔌 Ports Define input/output count and types
⚙️ Properties Add parameters (string / number / boolean / select) — accessible in code via self.args['property_name']
🌐 Sharing "Make public" toggle for community sharing

Right panel (60%) — Code Editor:

Feature Details
📝 Monaco editor Full syntax highlighting, same experience as built-in Python UDF
📄 Template Pre-filled pytexera boilerplate
▶️ Test Run Syntax validation before saving

🎯 Drag & Drop in Workflow Editor

Once saved, custom operators appear in the operator panel under a "My Operators" category:

  • Shows alongside built-in operators
  • Drag onto canvas → creates a node pre-filled with saved code, custom display name, and configured ports
  • Works exactly like any built-in operator — connect, configure, run

⚙️ How It Works Under the Hood

Custom operators are a smart wrapper around Python UDF — no engine modifications:

What happens How
Drag custom operator Creates a standard PythonUDFV2 node
Saved code Injected into the operator's code field
Custom properties Rendered as PROPS = {...} dictionary prepended to code
Ports Mapped to UDF's dynamic port configuration
Display name customDisplayName shows your operator name instead of "Python UDF"

Result: Zero engine changes, full compatibility with existing execution infrastructure.


🎬 Demo Walkthrough

  1. ➕ Open "My Operators""+ Create Operator"
  2. 🏷️ Name: "BMI Calculator", icon: 📊
  3. 🔌 Configure 1 input port, 1 output port
  4. 📝 Write code:
    df['BMI'] = df['weight'] / (df['height'] / 100) ** 2
    yield df
  5. 💾 Save → operator card appears in My Operators page
  6. 🖥️ Open a workflow → left panel shows "My Operators" category
  7. 🎯 Drag "BMI Calculator" onto canvas → Python UDF node appears with code pre-filled
  8. ▶️ Connect to data source and run

📸 Screenshots

Screenshot 2026-05-16 at 11 19 16 AM Screenshot 2026-05-16 at 11 19 30 AM Screenshot 2026-05-16 at 11 19 41 AM ---

🏗️ Architecture

┌──────────────────────────────────────────────────────┐
│  🖥️  Frontend (Angular)                              │
│                                                      │
│  New Components                                      │
│  • My Operators page (grid, create, edit, delete)    │
│  • Full-page editor (Monaco + config panels)         │
│  • Draggable custom operator label in operator menu  │
│                                                      │
│  New Services                                        │
│  • custom-operator.service (CRUD, localStorage)      │
│  • custom-operator-factory.service (builds           │
│    PythonUDFV2 predicate from saved config)          │
│                                                      │
│  Modified (additive only)                            │
│  • 3 new routes, sidebar link, operator menu panel,  │
│    dragStartedCustom() in drag-drop service          │
├──────────────────────────────────────────────────────┤
│  🔒 Texera Core Engine (Amber) — UNMODIFIED          │
│  Custom operators are PythonUDFV2 wrappers —         │
│  no registry changes, no engine changes              │
└──────────────────────────────────────────────────────┘

🔒 Zero modifications to Texera's core engine


✅ Testing

Test Status
Angular typecheck ✅ Clean
Create operator → save to localStorage ✅ Pass
Operator appears in panel ✅ Pass
Drag to canvas → creates PythonUDFV2 with pre-filled code ✅ Pass
Edit / delete ✅ Pass

💡 Why This Matters

Every data science platform has built-in operators. Almost none let users create their own without touching the engine internals. This turns every lab's common Python functions into first-class, drag-and-drop, shareable operators — with zero infrastructure changes.

Copy-paste the same Python UDF into every new workflow, hope everyone uses the latest version

Save once → drag and drop forever → update in one place → everyone gets the fix

Emily Sun and others added 2 commits May 15, 2026 21:55
This bundles the feature work that built up on this branch:

- Custom agents: dashboard CRUD page and editor dialog (48px icon tile,
  chip-style guardrails, model selector). Each custom agent now carries a
  LiteLLM model_name (Opus 4.7 / Haiku 4.5) that is passed through to the
  agent-service so different agents can use different models.

- Conversation history is scoped per (workflowId, agentId): switching
  agent or workflow yields a different conversation list. localStorage
  key: texera.workflowConversations.v1.{workflowId}.{agentId}.

- Time machine: workflow snapshot list, revert, and agent-tagged
  checkpoints. New workflow-history-tool in agent-service backs the
  "undo my last change" flow; amber gains a WorkflowSnapshotResource;
  sql/updates/23.sql adds the snapshot table.

- Operator-aware custom-agent prompts: the system prompt now injects the
  full operator catalog with a "prefer built-in operators over Python
  UDFs" rule, sourced from WorkflowSystemMetadata at request time.

- LiteLLM: added the claude-opus-4.7 entry alongside claude-haiku-4.5
  and gpt-5-mini in bin/litellm-config.yaml.

- Agent panel rewritten around the (conversation list / chat) two-view
  model with subscription-managed list reloads and per-step persistence.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a "My Operators" section under Your Work where users can author
Python operators by writing UDF code, configuring ports/properties,
and saving them as draggable items in the workflow editor. Each saved
operator wraps a PythonUDFV2 node pre-filled with the saved code and
ports — no engine or operator-registry changes required.

- Data model + localStorage CRUD (custom-operator.{interface,service})
- "My Operators" list page + full-page editor with Monaco code editor,
  port/property builder, and a Test Run that validates UDF shape
- Operator panel surfaces a "My Operators" collapse at the top of the
  workflow editor; dragging a custom operator builds a PythonUDFV2
  predicate via CustomOperatorFactoryService and reuses the existing
  DragDropService flow via a new dragStartedCustom() entry point
- Custom properties get rendered as a PROPS dict prepended to the saved
  code so user UDFs can read self-configured values without extending
  the Python UDF schema

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added engine ddl-change Changes to the TexeraDB DDL frontend Changes related to the frontend GUI dev common agent-service labels May 16, 2026
@Yicong-Huang
Copy link
Copy Markdown
Contributor

Thank you for participating in the hackathon. We really enjoyed your idea and appreciate the contribution.

We are now archiving hackathon submissions by closing the submission PRs. However, we strongly encourage you to continue developing your idea and explore the possibility of merging it into the main branch.

To move forward, please:

  1. Open an issue describing your idea, and link this PR as a reference.
  2. Discuss the design and implementation plan with us in the issue.
  3. Open smaller, focused PRs so they can go through proper review.

Thanks again for your participation and contribution!

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

Labels

agent-service common ddl-change Changes to the TexeraDB DDL dev engine frontend Changes related to the frontend GUI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants