Documentation
¶
Overview ¶
Package mcp — Data Tables MCP surface. Mirrors the n8n Data Table node + tab: schema CRUD + row CRUD + condition-based filtering.
Package mcp — workflow_describe implementation.
One call returns a human-readable summary of a workflow: triggers, graph shape (entry/leaves/node count), declared dependencies (channels, connector modules, providers), plus a `issues` list of dangling edge targets and templates pointing at undeclared nodes.
Designed as the "give me the lay of the land" call AI authors make before editing — replaces hand-walking workflow_get YAML.
Package mcp — diagnose: error-class classifier + suggested-fix builder. Surface point is the `diagnose=true` flag on workflow_get_run_log; this file is pure (RunState + Workflow + a few registries → Diagnosis) so a future workflow_watch diagnose-on-walk can re-use it without round-tripping back through the connector.
Design rules:
Classifier is a registry of regex rules, not a switch. Adding a new error class = drop a new entry. Each rule is a self-contained (pattern, handler) pair.
Handlers run with a DiagnoseCtx that carries the run, the workflow, and the registries they need to suggest a fix (Integration for channel events/actions, Connectors for connector ops, Providers for skills). When a registry is nil the handler should degrade gracefully — diagnosis still surfaces the raw error and "I don't know" instead of crashing.
Per the no-auto-fix discipline: the result carries a SuggestedFix description, never applies it. AI / user runs workflow_update_node / workflow_set_triggers to act on it.
Package mcp bundles every MCP operation the workflow surface exposes. Wire each method into the existing internal/mcp dispatch layer — transport-agnostic (stdio or HTTP). See workflow-design §9 for the catalog.
Package mcp — workflow_node_detail implementation.
One MCP op resolves a `node_type` key (built-in node, channel event/action, connector op, trigger type) to a unified detail response. Source-of-truth descriptors stay where they live (engine.NodeDescriptor, integration.EventDescriptor / ActionDescriptor, connector.Operation, engine.TriggerDescriptor) — this file is the projector that lifts each one into the same `NodeDetail` JSON shape so AI clients can fetch detail without knowing the per-source struct.
Key format (mirrored in the wick-workflow MCP guide):
agent built-in node channel:slack.message channel trigger event channel:slack.send_message channel action connector:slack.chat_postMessage connector op trigger:cron trigger type
All optional fields from wickdocs.Docs are flattened into the response; empty fields are omitted via json:",omitempty" so the AI never branches on null.
Package mcp — workflow_picker_resolve implementation.
Picker fields (channel_id whitelist, user whitelist, etc.) accept only `[{id, name}, ...]` JSON. AI authoring a match filter has to resolve the actual IDs from text the user typed ("#support", "yoga@example.com"). Without help it tends to guess C123 / U456 shapes — which always fail.
workflow_picker_resolve maps a `source` name (matching the wick:"picker=<source>" tag on the field) to a list of `{id, name}` items. The pickers themselves live in setup-injected functions so this package stays free of channel/connector imports.
Package mcp — workflow_template_test implementation.
One-shot Go template renderer that AI clients call to verify a `{{...}}` snippet against a synthetic context without round-tripping through a full edit + workflow_simulate cycle. Errors are introspected: when a missing-key error fires inside a map lookup, the response lists the keys that ARE present at the offending path so the next attempt is informed instead of guessing again.
Package mcp — workflow_validate hint augmentation.
parse.Validate already covers structural errors well; this layer wraps the result with did-you-mean suggestions for the failure modes AI authors hit repeatedly:
- lowercase JSON keys ("channel" / "channelname" instead of PascalCase ChannelName) when calling set_triggers
- misspelt match keys (channe_id instead of channel_id)
- templates pointing at .Event.Foo when the supported root is .Event.Payload
Hints are advisory — surfaced alongside the original Error.Message so existing callers keep working. The Ops.ValidateRich method is the workflow_validate handler going forward; Ops.Validate stays as the low-level shim.
Package mcp — workflow_watch implementation.
Watch is deliberately bounded:
Reads come from the sharded run index. Per-run state.Load only happens when a filter needs node_id / trigger_id, and even then it stops the moment `limit` results are collected.
wait_seconds is an UPPER bound. The handler subscribes to Engine's event broker, returns the instant the target count is met, and otherwise waits the remaining time.
All inputs are caps (limit ≤ 50, wait_seconds ≤ 30). AI can never trigger a long-running scan by accident.
See doc 25 for the full design notes.
Index ¶
- Constants
- func WorkspaceFormatContracts() map[string]any
- type CanvasStats
- type CanvasViewResult
- type CanvasViewRow
- type CreateInput
- type DataTableCreateInput
- type DataTableDeleteInput
- type DataTableInsertInput
- type DataTableQueryInput
- type DataTableSummary
- type DescribeDeps
- type DescribeIssue
- type DescribeResult
- type DiagnoseCtx
- type Diagnosis
- type ErrorHint
- type ExecNodeInput
- type GraphSummary
- type NodeDetail
- type NodeTypeInfo
- type Ops
- func (m *Ops) AddNode(id string, n workflow.Node) (workflow.Workflow, error)
- func (m *Ops) AutoLayout(id string, nodeIDs []string) (workflow.Workflow, error)
- func (m *Ops) CanvasView(id string) (CanvasViewResult, error)
- func (m *Ops) ChannelsList() []channel.Info
- func (m *Ops) Connect(id, from, to, caseLabel string) (workflow.Workflow, error)
- func (m *Ops) ConnectorsList() []connector.Info
- func (m *Ops) Create(in CreateInput) (workflow.Workflow, error)
- func (m *Ops) DataTableCount(in DataTableDeleteInput) (int, error)
- func (m *Ops) DataTableCreate(in DataTableCreateInput) error
- func (m *Ops) DataTableDelete(in DataTableDeleteInput) (int, error)
- func (m *Ops) DataTableDrop(slug string) error
- func (m *Ops) DataTableGet(slug string) (map[string]any, error)
- func (m *Ops) DataTableInsert(in DataTableInsertInput) error
- func (m *Ops) DataTableList() ([]DataTableSummary, error)
- func (m *Ops) DataTableQuery(in DataTableQueryInput) ([]map[string]any, error)
- func (m *Ops) DataTableUpdateSchema(slug string, sc datatable.Schema) error
- func (m *Ops) DataTableUpsert(in DataTableInsertInput) (string, error)
- func (m *Ops) Delete(id string) error
- func (m *Ops) DeleteNode(id, nodeID string) (workflow.Workflow, error)
- func (m *Ops) DeleteTest(id, name string) error
- func (m *Ops) Describe(id string) (DescribeResult, error)
- func (m *Ops) Diagnose(ctx context.Context, w workflow.Workflow, st workflow.RunState) Diagnosis
- func (m *Ops) DiffVersions(id string, fromID, toID uint) (VersionDiff, error)
- func (m *Ops) Disconnect(id, from, to string) (workflow.Workflow, error)
- func (m *Ops) ExecNode(ctx context.Context, id string, body ExecNodeInput) (map[string]any, error)
- func (m *Ops) Get(id string) (workflow.Workflow, error)
- func (m *Ops) GetRunSummaries(id string, page, pageSize int) ([]RunSummary, bool, error)
- func (m *Ops) GetRuns(id string, limit int) ([]string, error)
- func (m *Ops) GetTest(id, name string) ([]byte, error)
- func (m *Ops) GuardReport(ctx context.Context, id string) (guard.Report, error)
- func (m *Ops) IntegrationActions() []integration.ActionDescriptor
- func (m *Ops) IntegrationEvents() []integration.EventDescriptor
- func (m *Ops) List() ([]Summary, error)
- func (m *Ops) ListTests(id string) ([]string, error)
- func (m *Ops) MoveNode(id, nodeID string, x, y int) (workflow.Workflow, error)
- func (m *Ops) MoveNodes(id string, moves []canvas.NodeMove) (workflow.Workflow, error)
- func (m *Ops) NodeDetail(nodeType string) (NodeDetail, error)
- func (m *Ops) NodeTypes() []NodeTypeInfo
- func (m *Ops) PickerResolve(ctx context.Context, in PickerResolveInput) (PickerResolveResult, error)
- func (m *Ops) ProvidersList() []provider.Info
- func (m *Ops) RestoreVersion(id string, versionID uint, createdBy string) (uint, error)
- func (m *Ops) RunNow(ctx context.Context, id string, evt workflow.Event) error
- func (m *Ops) RunNowWith(ctx context.Context, id string, w *workflow.Workflow, evt workflow.Event) error
- func (m *Ops) SaveTest(id, name string, body []byte) error
- func (m *Ops) SetLock(id string, locked bool) error
- func (m *Ops) SetTriggers(id string, triggers []workflow.Trigger) (workflow.Workflow, error)
- func (m *Ops) Simulate(ctx context.Context, id string, evt workflow.Event) (workflow.RunState, error)
- func (m *Ops) SkillsList(ctx context.Context, providerName string) ([]provider.Skill, error)
- func (m *Ops) TemplateTest(in TemplateTestInput) (TemplateTestResult, error)
- func (m *Ops) Toggle(id string, enabled bool) (workflow.Workflow, error)
- func (m *Ops) TriggerTypes() []TriggerTypeInfo
- func (m *Ops) UpdateNode(id, nodeID string, patch map[string]any) (workflow.Workflow, error)
- func (m *Ops) Validate(id string) ValidateResult
- func (m *Ops) ValidateRich(id string) ValidateRichResult
- func (m *Ops) VersionDetail(versionID uint) (entity.WorkflowVersion, error)
- func (m *Ops) Versions(id string) ([]VersionSummary, error)
- func (m *Ops) Watch(ctx context.Context, in WatchInput) (WatchResult, error)
- func (m *Ops) WithIntegration(reg *integration.Registry) *Ops
- func (m *Ops) Workspace() map[string]any
- type PickerFunc
- type PickerItem
- type PickerRegistry
- type PickerResolveInput
- type PickerResolveResult
- type RunSummary
- type SuggestedFix
- type Summary
- type TemplateTestInput
- type TemplateTestResult
- type TriggerSummary
- type TriggerTypeInfo
- type ValidateResult
- type ValidateRichResult
- type VersionDiff
- type VersionSummary
- type WatchInput
- type WatchResult
- type WatchRow
Constants ¶
const ( KindBuiltIn = "built_in" KindChannelEvent = "channel_event" KindChannelAction = "channel_action" KindConnectorOp = "connector_op" KindTrigger = "trigger" )
Detail kinds, exposed via NodeDetail.Kind.
Variables ¶
This section is empty.
Functions ¶
func WorkspaceFormatContracts ¶
WorkspaceFormatContracts returns structured format rules AI must follow when writing workflow YAML or trigger JSON. Exposed via workflow_workspace so AI reads them once at session start instead of relying on prose descriptions.
Types ¶
type CanvasStats ¶ added in v0.14.20
type CanvasStats struct {
NodeCount int `json:"node_count"`
TriggerCount int `json:"trigger_count"`
EdgeCount int `json:"edge_count"`
Unpositioned int `json:"unpositioned"`
}
CanvasStats summarises the canvas composition.
type CanvasViewResult ¶ added in v0.14.20
type CanvasViewResult struct {
Nodes []CanvasViewRow `json:"nodes"`
Triggers []CanvasViewRow `json:"triggers"`
ASCII string `json:"ascii"`
Stats CanvasStats `json:"stats"`
}
CanvasViewResult is the response for workflow_canvas_view.
type CanvasViewRow ¶ added in v0.14.20
type CanvasViewRow struct {
ID string `json:"id"`
Label string `json:"label,omitempty"`
Type string `json:"type"`
X int `json:"x"`
Y int `json:"y"`
EdgesTo []string `json:"edges_to,omitempty"`
}
CanvasViewRow is one entry in the canvas table (node or trigger).
type CreateInput ¶
type CreateInput struct {
ID string `json:"id,omitempty"`
Template string `json:"template,omitempty"`
Name string `json:"name,omitempty"`
}
CreateInput is the payload for `workflow_create`.
ID is the on-disk folder name. Optional — when empty, Create generates a UUID so renaming the display name later doesn't break run history, indexed logs, or shared edit URLs. Power users (MCP, CLI, tests) may pin an explicit id for human-readable folders.
type DataTableCreateInput ¶ added in v0.13.1
type DataTableCreateInput struct {
Slug string `json:"slug"`
Mode string `json:"mode,omitempty"`
PrimaryKey []string `json:"primary_key,omitempty"`
Columns []datatable.Column `json:"columns"`
Access *datatable.Access `json:"access,omitempty"`
}
DataTableCreateInput is the payload for datatable_create.
type DataTableDeleteInput ¶ added in v0.13.1
type DataTableDeleteInput struct {
Slug string `json:"slug"`
Where map[string]any `json:"where,omitempty"`
Conditions []datatable.Condition `json:"conditions,omitempty"`
}
DataTableDeleteInput is the payload for datatable_delete.
type DataTableInsertInput ¶ added in v0.13.1
DataTableInsertInput is the payload for datatable_insert / upsert.
type DataTableQueryInput ¶ added in v0.13.1
type DataTableQueryInput struct {
Slug string `json:"slug"`
Where map[string]any `json:"where,omitempty"`
Conditions []datatable.Condition `json:"conditions,omitempty"`
OrderBy []workflow.DataTableOrder `json:"order_by,omitempty"`
Limit int `json:"limit,omitempty"`
Offset int `json:"offset,omitempty"`
}
DataTableQueryInput is the payload for datatable_query.
type DataTableSummary ¶ added in v0.13.1
type DataTableSummary struct {
Slug string `json:"slug"`
Name string `json:"name,omitempty"`
Mode string `json:"mode,omitempty"`
Columns int `json:"columns"`
RowCount int `json:"row_count"`
}
DataTableSummary is the row shape for datatable_list.
type DescribeDeps ¶
type DescribeDeps struct {
Channels []string `json:"channels,omitempty"`
Connectors []string `json:"connectors,omitempty"`
Providers []string `json:"providers,omitempty"`
Other map[string][]string `json:"other,omitempty"`
}
DescribeDeps lists external surfaces the workflow touches.
Channels / Connectors / Providers stay as flat string lists so existing callers / UIs keep working. Other dependency kinds (sheets, webhooks, custom) surface under Other, keyed by Kind.
type DescribeIssue ¶
type DescribeIssue struct {
Level string `json:"level"`
Message string `json:"message"`
Path string `json:"path,omitempty"`
}
DescribeIssue is one anomaly found during the walk. Level is "warning" or "error"; Message + Path tell the caller where to look.
type DescribeResult ¶
type DescribeResult struct {
ID string `json:"id"`
Name string `json:"name"`
Enabled bool `json:"enabled"`
Summary string `json:"summary,omitempty"`
Triggers []TriggerSummary `json:"triggers"`
Graph GraphSummary `json:"graph"`
Dependencies DescribeDeps `json:"dependencies"`
Issues []DescribeIssue `json:"issues,omitempty"`
}
DescribeResult is the workflow_describe response.
type DiagnoseCtx ¶
type DiagnoseCtx struct {
Ctx context.Context
State workflow.RunState
Workflow workflow.Workflow
Integration *integration.Registry
Connectors *connector.Registry
Providers *provider.Registry
// Match is the regex submatch slice (Match[0] is the full hit;
// Match[1..] are capture groups). Always populated for rules that
// supply a pattern.
Match []string
}
DiagnoseCtx is the surface a classifier rule sees. Kept small and explicit so rules don't reach into mcp.Ops directly.
type Diagnosis ¶
type Diagnosis struct {
ErrorClass string `json:"error_class,omitempty"`
FailedNode string `json:"failed_node,omitempty"`
Field string `json:"field,omitempty"`
Summary string `json:"diagnosis,omitempty"`
AvailableKeys []string `json:"available_keys,omitempty"`
SuggestedFix *SuggestedFix `json:"suggested_fix,omitempty"`
PathTaken []string `json:"path_taken,omitempty"`
NextActions []string `json:"next_actions,omitempty"`
Status string `json:"status,omitempty"`
}
Diagnosis is the structured response attached to a failed-run reply when the caller passed `diagnose=true`. A successful run still gets a Diagnosis, but with ErrorClass empty and PathTaken populated.
type ErrorHint ¶
type ErrorHint struct {
Path string `json:"path"`
Message string `json:"message"`
DidYouMean []string `json:"did_you_mean,omitempty"`
Hint string `json:"hint,omitempty"`
}
ErrorHint extends parse.Error with optional remediation pointers.
type ExecNodeInput ¶ added in v0.14.20
type ExecNodeInput struct {
Node workflow.Node `json:"node"`
Input map[string]any `json:"input"`
Event map[string]any `json:"event"`
ParentID string `json:"parent_id"`
NodeOutputs map[string]map[string]any `json:"node_outputs"`
}
ExecNodeInput is the request shape for ExecNode.
type GraphSummary ¶
type GraphSummary struct {
Entry string `json:"entry,omitempty"`
NodeCount int `json:"node_count"`
EdgeCount int `json:"edge_count"`
Leaves []string `json:"leaves,omitempty"`
NodeTypes []string `json:"node_types,omitempty"`
}
GraphSummary describes the DAG's shape.
type NodeDetail ¶
type NodeDetail struct {
NodeType string `json:"node_type"`
Kind string `json:"kind"`
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
WhenToUse string `json:"when_to_use,omitempty"`
Destructive bool `json:"destructive,omitempty"`
Schema map[string]any `json:"schema,omitempty"`
Output map[string]any `json:"output,omitempty"`
MatchSchema map[string]any `json:"match_schema,omitempty"`
Example string `json:"example,omitempty"`
wickdocs.Docs
}
NodeDetail is the unified `workflow_node_detail` response.
Kind is set per-source so the AI can disambiguate which prefix to re-use when chasing PairWith links; it is informational only.
type NodeTypeInfo ¶
type NodeTypeInfo struct {
Type string `json:"type"`
Description string `json:"description"`
Schema map[string]any `json:"schema"`
Example string `json:"example,omitempty"`
WhenToUse string `json:"when_to_use"`
// Palette metadata mirrored from engine.NodeDescriptor so the
// editor's Add Node picker can render category/label/badge
// straight from this row instead of carrying a parallel map.
Category string `json:"category,omitempty"`
Label string `json:"label,omitempty"`
Badge string `json:"badge,omitempty"`
}
NodeTypeInfo is one row of the node-type catalog.
func NodeTypesCatalog ¶
func NodeTypesCatalog(eng *engine.Engine) []NodeTypeInfo
NodeTypesCatalog returns the AI-introspectable node type metadata, built entirely from Engine.Descriptors — single source of truth lives in each node executor's Descriptor() method.
type Ops ¶
type Ops struct {
Service service.Service
Engine *engine.Engine
Router *trigger.Router
Canvas *canvas.Canvas
Channels *channel.Registry
Connectors *connector.Registry
Providers *provider.Registry
DataTables datatable.Service
StateStore state.Store
Integration *integration.Registry
// Guard runs safety policy rules (destructive shell, secret leak,
// SQL injection, network allowlist). Powers workflow_guard. Nil
// when not wired — handler returns 503-equivalent.
Guard *guard.Guard
// Repo is the DB-backed workflow store. Nil when no DB is wired —
// version history + restore handlers fall back to the file-store
// equivalents the Service surfaces.
Repo *repository.Repo
// Pickers maps picker source names (e.g. "slack.channels") to
// resolver functions wired at setup. Powers workflow_picker_resolve.
// Always non-nil after New(); setup code registers sources via
// Pickers.Register(...). See picker.go.
Pickers *PickerRegistry
}
Ops bundles every MCP operation surface.
func New ¶
func New(svc service.Service, e *engine.Engine, router *trigger.Router, c *canvas.Canvas, channels *channel.Registry, connectors *connector.Registry, providers *provider.Registry, dataTables datatable.Service, ss state.Store) *Ops
New wires the dispatcher.
func (*Ops) AutoLayout ¶ added in v0.14.20
AutoLayout wraps Canvas.AutoLayout — DAG-aware position compute + apply.
func (*Ops) CanvasView ¶ added in v0.14.20
func (m *Ops) CanvasView(id string) (CanvasViewResult, error)
CanvasView returns a human-readable table + ASCII sketch of the workflow canvas. Pure read — no side effects.
func (*Ops) ChannelsList ¶
ChannelsList returns the channel registry introspection rows.
func (*Ops) ConnectorsList ¶
ConnectorsList returns the connector registry introspection rows.
func (*Ops) Create ¶
func (m *Ops) Create(in CreateInput) (workflow.Workflow, error)
Create scaffolds a new workflow from a template.
func (*Ops) DataTableCount ¶ added in v0.13.1
func (m *Ops) DataTableCount(in DataTableDeleteInput) (int, error)
DataTableCount counts rows.
func (*Ops) DataTableCreate ¶ added in v0.13.1
func (m *Ops) DataTableCreate(in DataTableCreateInput) error
DataTableCreate registers a new table.
func (*Ops) DataTableDelete ¶ added in v0.13.1
func (m *Ops) DataTableDelete(in DataTableDeleteInput) (int, error)
DataTableDelete removes rows; Conditions wins over Where when both set.
func (*Ops) DataTableDrop ¶ added in v0.13.1
DataTableDrop removes a table and all its rows.
func (*Ops) DataTableGet ¶ added in v0.13.1
DataTableGet returns schema + sample rows for one table.
func (*Ops) DataTableInsert ¶ added in v0.13.1
func (m *Ops) DataTableInsert(in DataTableInsertInput) error
DataTableInsert inserts a new row.
func (*Ops) DataTableList ¶ added in v0.13.1
func (m *Ops) DataTableList() ([]DataTableSummary, error)
DataTableList returns every registered table with row count.
func (*Ops) DataTableQuery ¶ added in v0.13.1
func (m *Ops) DataTableQuery(in DataTableQueryInput) ([]map[string]any, error)
DataTableQuery returns rows matching either Where (equality) or Conditions (richer ops). When both are set, Conditions wins.
func (*Ops) DataTableUpdateSchema ¶ added in v0.13.1
DataTableUpdateSchema replaces the schema of an existing table.
func (*Ops) DataTableUpsert ¶ added in v0.13.1
func (m *Ops) DataTableUpsert(in DataTableInsertInput) (string, error)
DataTableUpsert insert-or-updates by PK.
func (*Ops) DeleteNode ¶
DeleteNode wraps Canvas.DeleteNode.
func (*Ops) DeleteTest ¶ added in v0.14.20
DeleteTest drops one test case by name.
func (*Ops) Describe ¶
func (m *Ops) Describe(id string) (DescribeResult, error)
Describe builds the summary for one workflow id.
func (*Ops) Diagnose ¶
Diagnose returns the structured diagnosis for a run. Success paths produce a Diagnosis with Status="success" + PathTaken populated. Failed paths classify the error and (when possible) propose a fix.
The function is safe to call with nil registries — handlers degrade to "I don't know" rather than crash.
func (*Ops) DiffVersions ¶ added in v0.14.20
func (m *Ops) DiffVersions(id string, fromID, toID uint) (VersionDiff, error)
DiffVersions resolves both version ids on the same workflow and returns their full bodies for client-side diff rendering.
func (*Ops) Disconnect ¶
Disconnect wraps Canvas.Disconnect.
func (*Ops) ExecNode ¶ added in v0.14.20
ExecNode runs one node in isolation — n8n's "Execute step" pattern. Returns the node output + latency. Nothing persists to runs/. The caller passes a prefill of upstream outputs via NodeOutputs so {{.Node.<upstream>}} template refs resolve.
func (*Ops) GetRunSummaries ¶
GetRunSummaries returns one page of recent runs, newest first. Reads from the sharded index (`runs/index/<date>-<seq>.jsonl`) instead of scanning the per-run subdirs, so the cost stays constant whether the workflow has 10 or 100,000 historical runs. hasMore=true when older pages exist.
func (*Ops) GuardReport ¶ added in v0.14.20
GuardReport runs guard.Review against the draft and returns the report. Distinct from workflow_validate — guard inspects safety policy (destructive shell, secret leak, unparameterized SQL, network allowlist) while validate inspects graph structure (cycles, schema).
func (*Ops) IntegrationActions ¶
func (m *Ops) IntegrationActions() []integration.ActionDescriptor
IntegrationActions returns every registered action descriptor.
func (*Ops) IntegrationEvents ¶
func (m *Ops) IntegrationEvents() []integration.EventDescriptor
IntegrationEvents returns every registered event descriptor across all channels. Includes MatchSchema + PayloadType for full filter discovery.
func (*Ops) ListTests ¶ added in v0.14.20
ListTests returns every test case name registered under the workflow.
func (*Ops) NodeDetail ¶
func (m *Ops) NodeDetail(nodeType string) (NodeDetail, error)
NodeDetail returns the unified detail for one node_type key, or an error when the key is malformed or not registered.
Resolution order is by prefix — `channel:`, `connector:`, `trigger:` route to the matching registry; everything else is treated as a built-in node type. Unknown keys return an "unknown node_type" error so AI clients see a clean signal rather than an empty payload.
func (*Ops) NodeTypes ¶
func (m *Ops) NodeTypes() []NodeTypeInfo
NodeTypes returns the catalog used by `workflow_node_types`. Built from Engine.Descriptors — populated by each executor's Descriptor().
func (*Ops) PickerResolve ¶
func (m *Ops) PickerResolve(ctx context.Context, in PickerResolveInput) (PickerResolveResult, error)
PickerResolve looks up the picker source and returns matching items. Filtering is applied client-side after the resolver returns so sources don't have to implement filtering uniformly.
func (*Ops) ProvidersList ¶
ProvidersList returns the provider registry introspection rows.
func (*Ops) RestoreVersion ¶ added in v0.14.20
RestoreVersion writes a historic snapshot back to the draft slot. No auto-publish — the user must hit Publish to make the restore live. Returns the new draft snapshot id.
func (*Ops) RunNow ¶
RunNow enqueues a manual run for one explicit id. Bypasses Enabled + trigger-match checks so admins can fire a disabled workflow from the UI Run-Now button. Compare with Router.Dispatch which is the trigger-source path.
func (*Ops) RunNowWith ¶
func (m *Ops) RunNowWith(ctx context.Context, id string, w *workflow.Workflow, evt workflow.Event) error
RunNowWith fires a single run with an explicit Workflow override. The UI uses this so Run Now executes the freshly-saved DRAFT (workflow.draft.yaml) without waiting for Publish — router's registered copy stays on the published version so cron / channel / webhook triggers keep firing live.
func (*Ops) SetLock ¶ added in v0.14.20
SetLock flips workflow.Canvas["locked"]. Dedicated path so toggling works even while the workflow IS locked (the regular SaveDraft would be blocked by Service.SaveDraft's lock guard); also skips validation — locking shouldn't fail because the draft has a half-built node.
func (*Ops) SetTriggers ¶
SetTriggers wraps Canvas.SetTriggers.
func (*Ops) Simulate ¶
func (m *Ops) Simulate(ctx context.Context, id string, evt workflow.Event) (workflow.RunState, error)
Simulate dry-runs a workflow with a synthetic event.
func (*Ops) SkillsList ¶
SkillsList returns the catalog from one or all providers.
func (*Ops) TemplateTest ¶
func (m *Ops) TemplateTest(in TemplateTestInput) (TemplateTestResult, error)
TemplateTest renders `in.Template` against the resolved context and returns a structured result.
func (*Ops) TriggerTypes ¶
func (m *Ops) TriggerTypes() []TriggerTypeInfo
TriggerTypes returns the catalog used by `workflow_trigger_types`.
func (*Ops) UpdateNode ¶
UpdateNode wraps Canvas.UpdateNode.
func (*Ops) Validate ¶
func (m *Ops) Validate(id string) ValidateResult
Validate runs parse + validate (no guard).
func (*Ops) ValidateRich ¶
func (m *Ops) ValidateRich(id string) ValidateRichResult
ValidateRich runs parse.Validate and decorates each Error with did-you-mean / hint pointers. Used by workflow_validate.
func (*Ops) VersionDetail ¶ added in v0.14.20
func (m *Ops) VersionDetail(versionID uint) (entity.WorkflowVersion, error)
VersionDetail returns one snapshot including its full body JSON. Used by the FE to populate the diff viewer when the user compares two versions side-by-side.
func (*Ops) Versions ¶ added in v0.14.20
func (m *Ops) Versions(id string) ([]VersionSummary, error)
Versions returns the history rows for a workflow ordered newest first. Powers the SPA history panel and the workflow_versions MCP op. Empty list when no DB is wired.
func (*Ops) Watch ¶
func (m *Ops) Watch(ctx context.Context, in WatchInput) (WatchResult, error)
Watch resolves runs matching the filter, optionally subscribing to the live engine broker for wait_seconds.
func (*Ops) WithIntegration ¶
func (m *Ops) WithIntegration(reg *integration.Registry) *Ops
WithIntegration wires the integration registry so workflow_integration can expose per-channel event + action descriptors (incl. MatchSchema) independent of the live Channel registry. Useful for stdio MCP where no Slack channel runs but AI still needs full filter schemas.
type PickerFunc ¶
type PickerFunc func(ctx context.Context, query string) ([]PickerItem, error)
PickerFunc is the per-source resolver signature. query is an optional case-insensitive substring filter the caller passes — the implementation MAY ignore it and return everything if filtering is cheap downstream.
type PickerItem ¶
PickerItem is one row a picker source returns. id is what the router matches against; name is shown to humans.
type PickerRegistry ¶
type PickerRegistry struct {
// contains filtered or unexported fields
}
PickerRegistry holds the wired (source → resolver) map. Concurrent- safe — registration happens at setup; reads happen per MCP call.
Wiring is intentionally external: setup code that owns the slack channel / connector instances calls Register("slack.channels", fn) rather than mcp importing slack. Keeps the mcp package free of channel-specific imports.
func NewPickerRegistry ¶
func NewPickerRegistry() *PickerRegistry
NewPickerRegistry constructs an empty registry. The Ops struct auto-creates one in New().
func (*PickerRegistry) Get ¶
func (r *PickerRegistry) Get(source string) (PickerFunc, bool)
Get returns the resolver for source, or (nil, false).
func (*PickerRegistry) Register ¶
func (r *PickerRegistry) Register(source string, fn PickerFunc)
Register adds (or replaces) one source. Idempotent — setup may call this multiple times during hot-reload.
func (*PickerRegistry) Sources ¶
func (r *PickerRegistry) Sources() []string
Sources lists the registered source names, sorted. Used in error messages so AI sees what IS available when it asks for something that's not.
type PickerResolveInput ¶
type PickerResolveInput struct {
Source string `json:"source"`
Query string `json:"query,omitempty"`
Limit int `json:"limit,omitempty"`
}
PickerResolveInput is the workflow_picker_resolve request.
type PickerResolveResult ¶
type PickerResolveResult struct {
Items []PickerItem `json:"items"`
// Truncated reports whether the resolver returned more items than
// the caller asked for (after Limit was applied).
Truncated bool `json:"truncated,omitempty"`
}
PickerResolveResult is the response.
type RunSummary ¶
type RunSummary struct {
ID string `json:"id"`
Status string `json:"status"`
StartedAt time.Time `json:"started_at"`
EndedAt *time.Time `json:"ended_at,omitempty"`
// Provenance fields — mirrored from the run's index entry so the
// editor can show source / trigger pills without re-loading each
// run's state.json. Empty for legacy runs that pre-date the
// IndexEntry change.
Source string `json:"source,omitempty"`
TriggerID string `json:"trigger_id,omitempty"`
TriggerType string `json:"trigger_type,omitempty"`
}
RunSummary is the lightweight row the editor's Runs panel shows — ID + started timestamp + status. Loaded eagerly because the panel only displays the most recent N runs (default 20) and one state.json read per run is cheap.
type SuggestedFix ¶
type SuggestedFix struct {
NodeID string `json:"node_id"`
Field string `json:"field,omitempty"`
Current string `json:"current,omitempty"`
Suggested string `json:"suggested,omitempty"`
Confidence string `json:"confidence"`
Rationale string `json:"rationale,omitempty"`
}
SuggestedFix carries a concrete patch the AI can show to the user before running workflow_update_node. confidence is one of "high" | "medium" | "low" — see doc 25 §"Confidence levels".
type Summary ¶
type Summary struct {
ID string `json:"id"`
Name string `json:"name"`
Enabled bool `json:"enabled"`
Version int `json:"version"`
CreatedAt time.Time `json:"created_at,omitempty"`
UpdatedAt time.Time `json:"updated_at,omitempty"`
}
Summary is the row shape for `workflow_list`.
type TemplateTestInput ¶
type TemplateTestInput struct {
Template string `json:"template"`
Context string `json:"context,omitempty"`
SampleEvent string `json:"sample_event,omitempty"`
}
TemplateTestInput is the payload for workflow_template_test.
Context is a JSON-encoded RenderCtx-shaped object. Top-level keys "Event", "Node", "Env", "Secret", "Workflow", "Run", "Dataset" are projected onto the typed RenderCtx; unknown keys are ignored so the caller can hand in whatever they have without ceremony.
SampleEvent picks a built-in synthetic event payload. When non-empty it OVERWRITES the .Event branch of context — the caller can use SampleEvent alone for the easy cases, or mix it with a hand-built .Node context for richer scenarios.
type TemplateTestResult ¶
type TemplateTestResult struct {
OK bool `json:"ok"`
Rendered string `json:"rendered,omitempty"`
Error string `json:"error,omitempty"`
At string `json:"at,omitempty"`
AvailableKeys []string `json:"available_keys,omitempty"`
Hint string `json:"hint,omitempty"`
}
TemplateTestResult is the workflow_template_test response.
On success Rendered carries the output and Error is empty. On failure Error explains the failure, and when the failure is a missing-key error wick introspects the context at the offending path and lists the keys that ARE present.
type TriggerSummary ¶
type TriggerSummary struct {
ID string `json:"id,omitempty"`
Type string `json:"type"`
EntryNode string `json:"entry_node"`
Schedule string `json:"schedule,omitempty"`
Channel string `json:"channel,omitempty"`
Event string `json:"event,omitempty"`
Path string `json:"path,omitempty"`
MatchOn string `json:"match_on,omitempty"`
}
TriggerSummary collapses a workflow.Trigger to the fields a human (or AI) needs at a glance.
type TriggerTypeInfo ¶
type TriggerTypeInfo struct {
Type string `json:"type"`
Description string `json:"description"`
Schema map[string]any `json:"schema"`
Example string `json:"example,omitempty"`
}
TriggerTypeInfo is one row of the trigger-type catalog.
func TriggerTypesCatalog ¶
func TriggerTypesCatalog() []TriggerTypeInfo
TriggerTypesCatalog returns the trigger-type metadata.
type ValidateResult ¶
type ValidateResult struct {
OK bool `json:"ok"`
Errors []parse.Error `json:"errors,omitempty"`
Warnings []parse.Error `json:"warnings,omitempty"`
}
ValidateResult is the response for `workflow_validate`.
type ValidateRichResult ¶
type ValidateRichResult struct {
OK bool `json:"ok"`
Errors []ErrorHint `json:"errors,omitempty"`
Warnings []ErrorHint `json:"warnings,omitempty"`
}
ValidateRichResult is the augmented response for workflow_validate.
Errors and Warnings carry the same Path + Message as parse.Result plus an optional DidYouMean / Hint pair. Hint is a human-readable remediation pointer the caller can show verbatim; DidYouMean lists likely-intended values for "unknown field" / "unknown key" errors.
type VersionDiff ¶ added in v0.14.20
type VersionDiff struct {
From entity.WorkflowVersion `json:"from"`
To entity.WorkflowVersion `json:"to"`
}
DiffVersions returns the body of two snapshots so the caller can render a diff. Body is shipped as JSON strings; the FE picks its own diff library to render.
type VersionSummary ¶ added in v0.14.20
type VersionSummary struct {
ID uint `json:"id"`
WorkflowID string `json:"workflow_id"`
Kind string `json:"kind"`
Message string `json:"message,omitempty"`
CreatedBy string `json:"created_by,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
VersionSummary is the narrow projection of one workflow_versions row callers actually need. Body is held back from the list view — fetching every snapshot's full JSON would balloon the response.
type WatchInput ¶
type WatchInput struct {
WorkflowID string `json:"workflow_id,omitempty"`
TriggerID string `json:"trigger_id,omitempty"`
NodeID string `json:"node_id,omitempty"`
Status string `json:"status,omitempty"` // any | success | failed | running
Since string `json:"since,omitempty"` // RFC3339 absolute or "-15m" relative
Limit int `json:"limit,omitempty"`
WaitSeconds int `json:"wait_seconds,omitempty"`
Expect int `json:"expect,omitempty"`
StopOnFirst bool `json:"stop_on_first,omitempty"`
}
WatchInput is the workflow_watch request shape.
type WatchResult ¶
type WatchResult struct {
Runs []WatchRow `json:"runs"`
CheckedUntil time.Time `json:"checked_until"`
Truncated bool `json:"truncated,omitempty"`
}
WatchResult is the response.
type WatchRow ¶
type WatchRow struct {
RunID string `json:"run_id"`
WorkflowID string `json:"workflow_id"`
Status string `json:"status,omitempty"`
TriggerID string `json:"trigger_id,omitempty"`
StartedAt time.Time `json:"started_at"`
EndedAt *time.Time `json:"ended_at,omitempty"`
}
WatchRow is one returned run summary. Deliberately tiny — downstream calls workflow_get_run_log per id when it wants more.