feat(custom-blocks): log and bill child runs in the publisher's workspace - #6023
feat(custom-blocks): log and bill child runs in the publisher's workspace#6023TheodoreSpeaks wants to merge 14 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryHigh Risk Overview Billing and visibility shift across the boundary: model spend is no longer rolled onto the consumer block or failed tool results; the consumer sees only curated outputs plus Agent-as-tool paths adopt the invoker’s Reviewed by Cursor Bugbot for commit b345750. Bugbot is set up for automated code reviews on this repo. Configure here. |
Greptile SummaryFollow-up review of custom-block boundary error classification and child-run billing/logging.
Confidence Score: 5/5This PR appears safe to merge with respect to the previously reported boundary-classification issues; those failures are resolved at HEAD. The unavailable and usage-limit consumer signals are wired through buildBoundaryFailure and BoundarySafeError as intended, and no remaining blocking failure from those threads is present.
|
| Filename | Overview |
|---|---|
| apps/sim/executor/handlers/workflow/workflow-handler.ts | Unavailable failures go through buildBoundaryFailure with consumerFacing errorType; admission and other boundary paths share the same classification path. |
| apps/sim/lib/workflows/custom-blocks/child-execution.ts | CustomBlockAdmissionError extends BoundarySafeError as usage_limit; payer vs actor messaging is sanitized before throw. |
| apps/sim/executor/execution/block-executor.ts | Propagates ChildWorkflowError.consumerFacing into errorType and errorRef on block output. |
Reviews (10): Last reviewed commit: "fix(agent): forward the execution id thr..." | Re-trigger Greptile
|
@cursor review |
|
@cursor review |
|
@cursor review |
|
@cursor review |
|
@cursor review |
|
@cursor review |
|
@cursor review |
|
@cursor review |
| // source workflow would bill if run directly, exactly as if it ran the key. | ||
| const childCost = aggregateChildCost(childTraceSpans) | ||
| return this.projectCustomBlockOutput(executionResult, exposedOutputs, childCost) | ||
| return this.projectCustomBlockOutput(executionResult, exposedOutputs) |
There was a problem hiding this comment.
Paused child treated as success
Medium Severity
Cancelled custom-block children are classified with a BoundarySafeError after the child session is finalized, but paused children (status: 'paused', success: true) are not. They go through safeComplete, then projectCustomBlockOutput, so a source HITL pause becomes a consumer success with incomplete outputs and a completed publisher log. CustomBlockErrorType has no paused member either.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit 67805cb. Configure here.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 264bc74. Configure here.


Summary
executionId, own logging session against the source (publisher's) workspace, own ledger rows. The publisher sees a full run with the trace waterfall in their own Logs; the consumer's view stays as opaque as before.custom_block_*, so it went unnoticed.buildCostCarrierSpanswrote toblockLog.childTraceSpans, but its only reader is gated onisWorkflowBlockType, which excludes custom blocks. Dissolves now that the child bills itself; both roll-ups deleted.childWorkflowNamestill holds the workflow id before it's resolved).BoundarySafeErrorso consumer visibility is a property decided at the throw site (fail-closed) instead of depending on whether a throw sits before or after thetry. Consumers now get a machine-readableerrorTypeplus an opaqueerrorRef(the child's execution id) they can quote in support.parseNestedWorkflowError/buildNestedWorkflowErrorMessage) in favour of a structuredworkflowChain. That also fixesWorkflow chain: Child → Child | err, which happened whenever a child returnedsuccess: falserather than throwing.readStatusCodenow walks.causeand readsHttpError/status/statusCode, with a narrow 503-only 5xx whitelist so an upstream 502/504 never becomes ours.buildBlockExecutionErrornow preservescause. Deletes deadbuildHTTPError.hasUnhandledError/traceSpansIndicateFailure.Behaviour changes worth flagging
mothershipblock recovered from a failed child span were previously loggedfailedbylogger.ts/logging-session.ts, which recursed past the error boundary thattrace-spans.tshonours. They now log as succeeded. Existing rows are not backfilled, so expect a step-change in dashboard failure rates.status === 500should be checked.Type of Change
Testing
Tested manually end-to-end across two workspaces in the same org: child run lands in the publisher's workspace with the full trace, consumer's row shows only its own
0.005base fee and no model cost, and the child resolves credentials against the source workspace (verified via BYOK — a publisher key correctly zeroes the charge, and removing it bills the source workspace).Full suite green:
type-check0 errors,lint:check, and all 11 CI audits (check:boundaries,check:api-validation:strict,check:utils,check:zustand-v5,check:react-query,check:client-boundary,check:bare-icons,check:icon-paths,check:realtime-prune,skills:check,agent-stream-docs:check). 15107/15108 tests pass — the one failure is a pre-existing local-env issue (cloud-review-toolsshells out to argbinary that isn't installed).Checklist