Skip to content

feat(automation): script-node outputVariable + interpolated inputs (pure-function pattern, #1870) - #1926

Merged
os-zhuang merged 1 commit into
mainfrom
feat/script-output-variable
Jun 15, 2026
Merged

feat(automation): script-node outputVariable + interpolated inputs (pure-function pattern, #1870)#1926
os-zhuang merged 1 commit into
mainfrom
feat/script-output-variable

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

The long-term design for flow functions, decided from the templates evaluation. A flow function (script node) is a pure compute step — and ALL data I/O stays declarative on the flow graph.

Why pure-function (not a data API on the function)

The AI templates wrote invoke_function expecting the function to update the record directly, but flow functions get FlowFunctionContext (input/variables/automation/logger) — no data API, by design. That boundary is correct for a metadata-first, AI-authored platform:

  • Visible: data effects stay on the flow graph (update_record), not hidden in code.
  • Governed: writes go through the engine's data path (RLS, tenancy, transactions, hooks) — a raw function data-API would bypass that (the managedBy is not enforced: generic CRUD bypasses better-auth on sys_team (data-integrity / security) #1591 class).
  • Build-checkable: declarative writes are validated at objectstack build; opaque function I/O is exactly the "passes build / fails at runtime" class this season fought.
  • Two-tier already correct: L2 hooks are the data-lifecycle layer (they get ctx.api); flow functions are orchestration compute.

So the fix makes the pure-function pattern ergonomic, not the imperative one work.

What's added

  • config.outputVariable — exposes the function's return value as a flow variable, so a later declarative node persists it.
  • config.inputs are interpolated against live flow variables (they were passed raw) — so a function can consume a prior node's output.
{id: 'ai',type: 'script',config: {function: 'helpdesk.aiTriageStub',inputs: {ticketId: '{record.id}'},outputVariable: 'ai'}},{id: 'apply',type: 'update_record',config: {objectName: 'helpdesk_ticket',filter: {id: '{record.id}'},fields: {ai_category: '{ai.ai_category}',ai_sentiment: '{ai.ai_sentiment}'}}},

Also

  • Skill: automation pitfall [WIP] Create a new release version #9 now teaches this pattern (function returns → outputVariable → update_record; hooks for data side effects).
  • Tests: +1 end-to-end (compute → outputVariable → downstream node interpolates {ai.field}); @objectstack/service-automation202 pass; check:skill-docs passes.

This is the framework foundation for the templates' #1870 remediation (restructure the 4 AI flows to function-returns + update_record).

🤖 Generated with Claude Code

…ure-function pattern, #1870)
Long-term design for flow functions (per the templates evaluation): a flow
`function` is a PURE compute step — inputs → return value — and ALL data I/O
stays declarative on the flow graph. This keeps the data layer visible, governed
(RLS/tenancy/transactions via the engine's data path), and build-checkable
(create/update_record nodes the build already validates) — rather than giving
functions a raw data API that hides writes and bypasses governance. (Data-
lifecycle side effects remain L2 hooks, which legitimately get ctx.api.)
Two enablers:
- `config.outputVariable` exposes the function's return value as a flow variable
→ a later update_record persists it (`fields: { ai_category: '{ai.ai_category}' }`).
- `config.inputs` are now interpolated against live flow variables, so a function
can consume a prior node's output (`inputs: { ticketId: '{record.id}' }`).
Skill: automation pitfall #9 now teaches the pure-function pattern (function
returns → outputVariable → update_record; hooks for data side effects).
+1 end-to-end test (compute → outputVariable → downstream node interpolates it);
service-automation 202; check:skill-docs passes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel

vercelBot commented Jun 15, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
specReadyReadyPreview, CommentJun 15, 2026 4:33pm

Request Review

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tests tooling labels Jun 15, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): packages/services.

5 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/guides/packages.mdx(via packages/services)
  • content/docs/guides/runtime-services/audit-service.mdx(via packages/services)
  • content/docs/guides/runtime-services/index.mdx(via packages/services)
  • content/docs/guides/runtime-services/settings-service.mdx(via packages/services)
  • content/docs/protocol/objectos/i18n-standard.mdx(via packages/services)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@os-zhuang
os-zhuang merged commit 1402be0 into mainJun 15, 2026
14 checks passed
@os-zhuang
os-zhuang deleted the feat/script-output-variable branch June 15, 2026 16:37
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/steststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@os-zhuang