Add a new step to a workflow. This is the recommended path for agent-authored workflows — call create_workflow({ name, goal }) first, then add_step one step at a time, then validate_workflow + publish_workflow. Each call returns per-step validation errors immediately, so a bad step type / prompt ...
Part of the Agentled server.
Free to start. No card required.
AI agents use add_step to create or modify resources in Agentled. Write operations carry medium risk because an autonomous agent could trigger bulk unintended modifications. Rate limits prevent a single agent session from making hundreds of changes in rapid succession. Argument validation ensures the agent passes expected values.
Without a policy, an AI agent could call add_step repeatedly, creating or modifying resources faster than any human could review. PolicyLayer's rate limiting ensures write operations happen at a controlled pace, and argument validation catches malformed or unexpected inputs before they reach Agentled.
Write tools can modify data. A rate limit prevents runaway bulk operations from AI agents.
{
"version": "1",
"default": "deny",
"tools": {
"add_step": {
"limits": [
{
"counter": "add_step_rate",
"window": "minute",
"max": 30,
"scope": "grant"
}
]
}
}
} See the full Agentled policy for all 119 tools.
These attack patterns abuse exactly the kind of access add_step gives an agent. Each links to the full case and the policy that stops it:
Other write tools across the catalogue. The same approach applies to each: rate-limit and validate the arguments.
Add a new step to a workflow. This is the recommended path for agent-authored workflows — call create_workflow({ name, goal }) first, then add_step one step at a time, then validate_workflow + publish_workflow. Each call returns per-step validation errors immediately, so a bad step type / prompt template / missing required field is caught before the next step is built on top of it. KG-First — before writing prompt content into a step Before writing an AI-step prompt that contains workspace-specific content (thesis, ICP criteria, scoring rubric, sector list, geo focus, brand voice, seed lists), check whether that content already lives in the workspace KG: call list_memories / list_knowledge_lists / get_knowledge_text. If it doesn't exist yet, seed it first (store_memory / upsert_knowledge_text) before adding this step. Then reference it at runtime in the prompt template via {{steps.read-kg.content}} rather than pasting the text inline. Boundary: strategy → KG; execution wiring → workflow context; workflow structure → workflow. Required step fields (all types) - id: stable string unique within the workflow. - type: one of the closed list — trigger, appAction, aiAction, aiActionWithTools, toolAction, code, knowledgeSync, return, milestone, share, wait, branch, parallel, loop, end_if, agentOrchestrator. Any other string is silently stripped by the runtime. - name: human-readable label. Non-terminal steps also need next: { stepId } pointing to the next step. Terminal steps (milestone, return) omit next. Minimal shape by type json // trigger (manual) { "id": "start", "type": "trigger", "name": "Manual Start", "pipelineStepStartConditions": { "trigger": { "type": "manual" } }, "next": { "stepId": "next-step" } } // aiAction — LLM prompt → structured JSON { "id": "analyze", "type": "aiAction", "name": "Analyze", "pipelineStepPrompt": { "template": "Analyze {{input.company_url}}", "responseStructure": { "summary": "string", "score": "number (0-100)" } }, "creditCost": 10, "next": { "stepId": "next-step" } } // appAction — call an app/integration action { "id": "enrich", "type": "appAction", "name": "Enrich Company", "app": { "id": "agentled", "actionId": "agentled.get-linkedin-company-from-url", "source": "native" }, "stepInputData": { "profileUrls": "{{input.company_url}}" }, "next": { "stepId": "next-step" } } // → call get_app_actions({ appId }) FIRST to get valid actionId + input field names for this app. // aiActionWithTools — LLM agent invoking runtime tools { "id": "research", "type": "aiActionWithTools", "name": "Research", "tools": [{ "type": "builtin", "name": "web_search", "builtinType": "web_search" }], "pipelineStepPrompt": { "template": "Research {{input.topic}}", "responseStructure": { "summary": "string" } }, "creditCost": 10, "next": { "stepId": "next-step" } } // → call list_models for valid builtinType values (web_search, workspace_memory, kg_search, …). // knowledgeSync — persist prior step output to a KG list { "id": "save", "type": "knowledgeSync", "name": "Save to KG", "knowledgeSync": { "source": { "stepId": "analyze", "resultsPath": "items" }, "listKey": "scored_companies", "fieldMapping": { "name": "name", "score": "score" } }, "next": { "stepId": "done" } } // milestone — terminal step for top-level workflows { "id": "done", "type": "milestone", "name": "Done" } Variable references - {{input.fieldName}} — input page field (defined in context.executionInputConfig.fields or context.inputPages[].configuration.fields). - {{steps.stepId.fieldName}} — output of a prior step. - {{currentItem.field}} — current item inside a loopConfig iteration. Trigger step inputs are referenced as {{input.X}}, not {{steps.trigger-id.X}} — common agent mistake. Composable step blocks When building multi-step workflows, apply these reusable patterns: - Search & Extract: aiAction (generate queries) → appAction (search) → aiAction (extract). Never pass raw input to search APIs. - Enrich & Score: appAction (fetch data) → aiAction (score). Always enrich before scoring. - Draft & Send: aiAction email → approval with onApproval.action="schedule-email". Use HTML bodies for open/click tracking. Do not use Gmail/Outlook send appActions unless explicitly requested. - Report & Notify: aiAction report with Config renderer → share step → aiAction notification email. Include {{steps.<shareStepId>.shareUrl}} in the email template and keep the body to an HTML overview + report link. - Scrape & Summarize: appAction (scrape) → aiAction (summarize). - Loop Enrich & Filter: loopConfig on first step only → appAction (enrich each) → aiAction (score/filter). Post-loop: aiAction to rank with entryConditions.criteria[{ type: "loop_completion" }] and onCriteriaFail: "wait". Do not use scope as the runtime wait/fan-in mechanism; it only declares explicit container membership. - Multi-phase KG pipeline: each phase reads its input status, processes rows, then advances them (kg.upsert-rows with initial status → kg.read-list by status → kg.update-rows to next status). Status values are user-defined per pipeline. Status is DB-indexed — always filter by a single equality value, never scan. Mark the next status BEFORE side-effects (email, share, Slack). (Source of truth: COMPOSABLE_STEP_BLOCKS in workflowPatternExamples.ts) Positioning Use insertAfter to place the step after an existing step ID. When rewireNext is true (default), the insertAfter step's next is updated to the new step, and the new step's next is set to what insertAfter previously pointed to — maintaining the chain. Validates step ID uniqueness. Respects draft snapshot routing for live workflows.. It is categorised as a Write tool in the Agentled MCP Server, which means it can create or modify data. Consider rate limits to prevent runaway writes.
Register the Agentled MCP server in PolicyLayer and add a rule for add_step: allow, deny, rate-limit, or require approval. Point your MCP client at the PolicyLayer proxy URL and the rule is enforced on every call, before it reaches Agentled. Nothing to install.
add_step is a Write tool with medium risk. Write tools should be rate-limited to prevent accidental bulk modifications.
Yes. Add a rate_limit block to the add_step rule in your PolicyLayer policy. For example, setting max: 10 and window: 60 limits the tool to 10 calls per minute. Rate limits are tracked per agent session and reset automatically.
Set action: deny in the PolicyLayer policy for add_step. The AI agent will receive a policy violation error and cannot call the tool. You can also include a reason field to explain why the tool is blocked.
add_step is provided by the Agentled MCP server (@agentled/mcp-server). PolicyLayer sits as a proxy in front of this server to enforce policies before tool calls reach the server.
Deterministic rules across all 119 Agentled tools. Per-identity grants. Full audit log. Live in minutes. Nothing to install.
Free to start. No card required.
4,600+ MCP servers and 31,000+ tools scanned and risk-classified.