Skip to content

ConnectorActionDescriptor declares nothing about whether an action reads or writes, so the platform cannot count what a connector_action did #4395

Description

@os-zhuang

Package: @objectstack/spec (packages/spec/src/integration/connector-descriptor.ts)
Found while wiring #4354's per-run summaries into connector_action.

The gap

ConnectorActionDescriptor describes an action's shape and nothing about its effect:

export interface ConnectorActionDescriptor {
  readonly key: string;
  readonly label: string;
  readonly description?: string;
  readonly inputSchema?: Record<string, unknown>;
  readonly outputSchema?: Record<string, unknown>;
}

So crm.push_opportunity and crm.lookup_account are indistinguishable to the runtime. Nothing in the authorable Connector schema fills this in either — registerConnector reads actions for dispatch only.

Why it matters now

#4354 makes every flow run report selected / acted, and selected > 0 AND acted = 0 over consecutive runs is the broken-sweep alert. For a connector_action the platform has to pick one of three answers, and two of them are wrong:

That is correct but weaker than it needs to be. A connector-driven flow currently contributes no signal at all: it can neither confirm work happened nor be flagged for doing none. Every ObjectStack app whose automation runs through connectors is in that blind spot.

Proposal

Let the action declare its effect, and let the runtime count it:

export interface ConnectorActionDescriptor {
  readonly key: string;
  readonly label: string;
  readonly description?: string;
  readonly inputSchema?: Record<string, unknown>;
  readonly outputSchema?: Record<string, unknown>;
  /**
   * What the action does upstream. `read` never mutates; `write` does.
   * Absent keeps today's behaviour — the run reports the effect as uncountable.
   */
  readonly effect?: 'read' | 'write';
}

Then connector_action reports acted: 1 for a successful write, acted: 0 for a read, and falls back to unmeasuredEffect only when the connector declared nothing. Optional on purpose: existing connectors keep working and lose nothing, and declaring it is a strict improvement rather than a migration.

Worth considering alongside it: a count rather than a boolean, for bulk actions that report how many upstream records they touched (outputSchema often already carries one). That can follow — the read/write split is the part that unblocks the alert.

Note the ADR-0076 D12 angle: this is a machine-readable surface that is currently silent rather than wrong, which is the right failure. The proposal is to let it be accurate.

Related: #4354 (the summaries this feeds), #4347 (the silent-failure class both exist to surface).

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions