Write your first workflow
To build a plugin without writing JSON, use Plugin Developer instead (Create a plugin in chat). This tutorial shows the files it produces, so you can review or edit them.
Goal: write a three-step workflow plugin by hand, import it and run it step by step.
Before you start: the client is connected and a model is configured.
The plugin turns meeting notes into an action list. One agent drafts the list; a second step checks every row against the notes; the last step finishes the run.
draft (ai) → check (ai_review) → done (publish)
1. Write plugin.json
Create a folder named meeting-actions and save this file in it as plugin.json:
{
"schemaVersion": 1,
"key": "meeting-actions",
"version": "1.0.0",
"name": "Meeting actions",
"description": "Turn meeting notes into an action list and check it against the notes.",
"author": "Your team",
"instructions": "Work only from the notes the user provides. Do not invent owners or dates.",
"entrypoints": { "conversation": true, "task": true, "automation": false },
"inputs": [
{
"key": "notes",
"type": "textarea",
"label": "Meeting notes",
"description": "Paste the notes or attach a file.",
"required": true
}
],
"capabilities": { "skills": [], "mcpServers": [], "secrets": [], "runtime": ["files"], "network": false },
"workflow": {
"nodes": [
{
"key": "draft",
"type": "ai",
"name": "Draft the action list",
"config": {
"prompt": "Read the meeting notes. Write deliverables/actions.md with one row per action: what, owner, due date, source line. Leave owner or date empty when the notes do not say.",
"timeoutSeconds": 1800
},
"capabilities": { "skills": [], "mcpServers": [], "secrets": [], "runtime": ["files"], "network": false },
"outputs": [
{ "key": "actions", "kind": "file", "path": "deliverables/actions.md", "label": "Action list", "required": true }
]
},
{
"key": "check",
"type": "ai_review",
"name": "Check against the notes",
"dependsOn": ["draft"],
"inputs": [
{ "key": "actions", "fromNode": "draft", "outputKey": "actions", "label": "Action list", "required": true }
],
"config": {
"prompt": "Check every row of the action list against the notes. Write review.json. Return outcome blocked if any owner or date is not in the notes.",
"timeoutSeconds": 900
},
"capabilities": { "skills": [], "mcpServers": [], "secrets": [], "runtime": ["files"], "network": false },
"outputs": [
{ "key": "verdict", "kind": "decision", "path": "review.json", "label": "Review result", "required": true }
]
},
{
"key": "done",
"type": "publish",
"name": "Finish",
"dependsOn": ["check"],
"config": { "message": "Action list checked." }
}
]
}
}
What each part does:
| Part | Why |
|---|---|
key, version | The stable identity. Change version whenever content changes |
inputs | The form shown when the plugin starts |
capabilities (top level) | The most this plugin may use. Here: files only, no network |
capabilities (per node) | What this step actually uses. It must be a subset of the top level |
outputs / inputs on nodes | draft declares a file; check receives exactly that file. Agents don't share chat history |
kind: "decision" | The review writes a structured JSON verdict, not free text |
publish node | Every workflow ends with one. It closes the run |
2. Package it
Zip the folder contents so that plugin.json is at the root, and name the file .soduwork-plugin.
macOS, Linux
cd meeting-actions
zip -r ../meeting-actions-1.0.0.soduwork-plugin .
Windows (PowerShell)
Compress-Archive -Path .\meeting-actions\* -DestinationPath .\meeting-actions-1.0.0.zip
Rename-Item .\meeting-actions-1.0.0.zip meeting-actions-1.0.0.soduwork-plugin
3. Import it
In the client, open Plugins, choose Add plugin → Import plugin, and select the file. The client runs the pre-check and installs the plugin on this computer. If something is wrong, the pre-check names the field.
4. Run it step by step
Start a new chat, type /, choose Debug plugin, and pick Meeting actions. Paste some made-up meeting notes as the input.
The debug card runs each step in order on this computer and shows:
- the agent's work for each step in the chat;
deliverables/actions.mdafterdraft, checked before it is handed on;- the verdict in
review.jsonaftercheck.
If check returns blocked, the run stops there. Fix the notes or the prompt and retry that step only.
Check that it worked
- The debug card shows all three steps as finished.
review.jsoncontains"outcome": "proceed".
Next
- Use a different harness (runtime) or model for
check: Hand-offs and routing - Every node type: Workflow nodes
- Share it: Publish to your organization