For Claude and Codex, install the official Erstan plugin with browser-based OAuth and authorize Build access. Use the Advanced API-key setup only for automation or MCP clients that do not support the plugin flow. See Connect a Coding Agent.
Backend-enforced guarantees
These restrictions are server controls, not prompt guardrails:create_agentalways creates a draft, andupdate_agentwrites a draft while preserving any retained published version.publish_agentvalidates the complete saved graph and publishes only the exact current revision/version. The authoring tool family exposes no archive or delete operation.test_agentruns the guarded current draft;run_agentis a separate capability that resolves only a retained published version.- Every call re-checks the connected user’s live workspace, team, and agent permissions. Advanced API keys use their creator’s live permissions.
update_agentandpublish_agentrequire an opaque revision, and the backend atomically rejects stale revisions before mutation. The client handles that result by re-reading and reconciling; it cannot bypass the check by retrying.validate_agentnever mutates, publishes, or executes the draft.- Skill package validation never saves or executes code. Skill creation is draft-only, full-package updates require
expectedVersion, and publication re-validates the current package. - User-authored Skill actions run only through the isolated E2B action runtime. Declaring
sideEffects: "none"disables action-runtime network access, but does not make workspace-authored code trusted or bypass write confirmation.
Authorize agent building
Install the plugin and authorize Build access for the normal interactive setup. This grants the connected-app permissions View agents, Build agents, Run agents, Publish agents, and View runs, plus read-only access to work, documents, and files. It does not grant task, document, or file writes.Advanced API-key setup
For a non-OAuth client, create a workspace API key in Settings → API Keys with both authoring scopes:
Scopes are exact and additive.
create_agent needs agents:write; update_agent, validate_agent, and publish_agent require both agents:read and agents:write. A practical authoring key therefore needs both scopes. The existing agents:list and agents:run scopes remain separate and apply only to discovering and running retained published versions.
Access model
An OAuth connection acts as the user who approved it; an API key acts as the user who created it. Erstan evaluates that person’s live workspace, team, and agent permissions on every tool call:get_agentcan read only an agent the connection owner can normally see.create_agentmust target an accessible team in the connection owner’s workspace.update_agent,validate_agent, andpublish_agentrequire the connection owner’s normal edit permission for the target agent. Publishing also re-checks visibility of its current home team when one is assigned.
Tools
tools/list advertises a tool only when the OAuth grant holds the corresponding connected-app permission or an advanced API key holds every scope shown below. The plugin’s Build profile supplies the standard authoring permissions.
MCP
get_agent reads authoring state, including drafts. list_agents under agents:list is intentionally different: it lists only retained published versions that can be run externally.Argument and response summary
get_agent_node_catalogaccepts optionalnodeType,builderSection, andincludeFieldDetailsfilters. SetincludeActionTypestotrueto include valid action types and optionally setmaxActionTypesfrom 10 to 500 (default 120). Its versioned, builder-visible response is the source of truth; hidden/internal nodes, event triggers, raw HTTP categories, and unsafe action names are filtered out.get_agent_builder_guidetakes no arguments and returns versioned builder guidance, including the external tool-policy and baseline-tool rules below.get_agenttakesagentIdand an optional positive integerversion. It returns{ "agent": { ... }, "builderUrl": "..." };agent.revisionis the current opaque write token. An explicit historical version also adds top-levelselectedVersion, whileagent.currentVersionstill identifies the actual current graph version.create_agentrequiresteamId,name,nodes, andedges. Optional metadata includesdescription,category,tags,difficulty,estimatedTime, andbehaviorType(interactiveorpipeline). The new agent is shared with the selected team, and its response includes the first opaquerevision.update_agentrequiresagentId, the latest opaquerevision, and at least one metadata or graph change.versionis an optional additional guard against editing a different current graph version. It does not move an agent to another team. Never decode, synthesize, or reuse an old revision.validate_agentcan validate a saved draft byagentId, or validate proposedname,behaviorType,nodes, andedgesbefore creation. Optional proposed fields overlay the saved graph whenagentIdis present. Its response includesagentId,version,valid, and structureddiagnosticswith severity, code, message, and relevant graph paths or IDs.publish_agentrequiresagentIdand the latest opaquerevision; passcurrentVersionas optionalversionfor a second guard. It returns the published authoring state pluspublished: trueandalreadyPublished. A current already-published version is a validated no-op. If a response is lost, callget_agent: matchingstatus: "published",currentVersion, andpublishedVersionconfirms success; otherwise do not retry with the stale pre-publish revision.- A canonical Skill package is
{ "version": 1, "entryPath": "SKILL.md", "files": [...], "actions": [...] }. Every action points to an included file and declaresruntime: "e2b",language, andsideEffects(noneorexternal). validate_agent_skillandcreate_agent_skillaccept the complete object as eitherpackageorpackageJson. Create also requires a displaynameand always returns a draft.get_agent_skillreturns the complete package asskill.packageJson. Send that complete package toupdate_agent_skillwith the latestskill.currentVersionasexpectedVersion; do not send only changed files.publish_agent_skillacceptsskillIdand the latestexpectedVersion. A stale version returnsskill_version_conflict; re-read and reconcile instead of overwriting newer work.
Recommended flow
- Call
get_agent_builder_guideonce at the start of the build. - Call
get_agent_node_catalogand choose only node types and fields present in the returned live catalog. - Construct the complete directed graph and call
create_agentwith the targetteamId. - Keep the returned agent ID, opaque
revision,currentVersion, andbuilderUrl. - Call
validate_agent. The backend requires the complete proposed definition to pass validation. If an existing agent has unrelated pre-existing errors, stop before writing and ask whether the user wants to expand the change to repair them. - Use
get_agentto re-read the persisted draft. For every update, pass its latest opaquerevision; optionally passcurrentVersionasversionfor an additional graph-version guard. Replace the stored revision with the new value returned by each successful update. - Use
test_agentwith the current draft version when an execution test is authorized, then inspect the returned run. After the user explicitly asks to make the validated draft live, callpublish_agentwith the latest revision and optional current version.
Manage a Skill package
Use the same authorized connection for reusable Skill packages:- Build the complete package, including
SKILL.md, every referenced text file or script, and action metadata. - Call
validate_agent_skilland resolve every error. Validation does not save or run the package. - Call
create_agent_skill; it always creates a draft. Review the returnedskill.packageJson. - For later changes, call
get_agent_skill, apply the intended edit to the complete package, and callupdate_agent_skillwith its latestcurrentVersionasexpectedVersion. Omitstatusto preserve it. A published Skill has no separate retained draft pointer, so an update to one changes its live package. - Publish only when explicitly requested by calling
publish_agent_skillwith the newly returnedcurrentVersion.
.erstan/skill-package.json; older SKILL.md-only archives remain valid. The manifest is transport metadata and is not included in packageJson.files.
Agent Builder skill
The official plugin installs and versions this Skill automatically. The reference below is for advanced MCP clients that cannot install the plugin; Claude and Codex plugin users should not paste a separate copy into their projects. It teaches other clients how to use the backend-enforced authoring workflow without treating prompt instructions as the security boundary.Create a draft
The exact argument schema is available through MCPtools/list. A create call includes the target team, agent metadata, and the complete node-and-edge graph:
revision for the next update. currentVersion may be passed as the optional version guard on update or validation, but it does not replace the required revision token for updates.
A decoded create response has this stable shape:
Update and validate
For an agent that has never been published,update_agent accepts editable metadata patches and optional complete replacement nodes and edges. Always pass the most recently returned revision; version is optional:
"valid": false; inspect diagnostics for graph or configuration errors. Validation never publishes and does not make the draft externally runnable.
Publish a validated draft
Publishing re-runs the external-authoring validation and the normal workflow publish checks before changing lifecycle state:agent_revision_conflict and publishes nothing. Re-read, reconcile the user’s intent, validate again, and ask before publishing a changed graph. Repeating publish_agent with the current revision after the version is already live returns alreadyPublished: true without creating another version.
External-authoring boundaries
The catalog and validation contract deliberately expose only builder-visible nodes and tools.Triggers
Externally authored start nodes may useinput_form, chat, schedule, or webhook. triggerType: "event" is not externally authorable at all. In particular, email.received remains app-only. To receive a webhook, use triggerType: "webhook" rather than an event trigger.
AI nodes and tool selection
Every externally authored AI/tool-capable node must explicitly set canonical top-leveldata.toolPolicy to a value advertised for that node by get_agent_node_catalog. AI Respond, AI Think, and AI Plan & Execute support auto_discover, pinned_only, and none. Other internal model and fixed-action AI nodes advertise only pinned_only and none. The saved top-level field is authoritative. Legacy or nested selection aliases such as input.toolPolicy, toolMode, toolsMode, autoSelectTools, and autoToolDomainSelection are rejected for external authoring; runtime and nested inputs can only narrow a saved policy and never promote it.
Use none when the model needs no tools; none exposes zero model tools in every run: no platform baseline, pinned, provider, discovered, workflow-edge, Task/artifact, or executable-skill tools. Attached Skill metadata may remain in context, but full Skill instructions never do. AI Respond retains its existing conversational pinned baseline under pinned_only. AI Think and AI Plan & Execute are stricter: outside an authorized assigned-Task run, pinned_only gives them canonical persisted agentTools or Plan & Execute selectedActions pins plus skill_execute for saved executable skillIds, plus the always-on Platform Internal Runtime tier (run plan ledger write_todos, bounded tool-result reads, isolated Workbench). A legacy saved Think or Plan node with no top-level policy is runtime-clamped to that same bounded surface, while new external definitions cannot omit the field. Across all capability profiles, any authorized assigned-Task run whose effective policy is not none may additionally restore only its Task/artifact model tools so it can service the bound task; this never grants Tool Hub discovery/meta tools or default Skill discovery.
Use auto_discover only for exploratory or low-risk general assistance. For AI Think and AI Plan & Execute, only an explicitly saved canonical top-level data.toolPolicy: "auto_discover" enables the expanded platform baseline, Tool Hub, and default Skill discovery. Default Skill discovery on those nodes also requires skillPolicy: "auto_discover"; skillPolicy never raises the tool-policy ceiling. Explicit pins remain available, and every discovered write retains the workspace execution policy. Pin any tool the workflow must have and retain its individual governance settings. auto_discover controls discovery only; it never changes an explicit per-tool writePolicy. Only a server-owned platformMinimumWritePolicy may make the effective execution policy stricter. Use pinned_only for deterministic, production, ERP/accounting, NetSuite, or write-capable work.
Attached skillIds are metadata-only candidates under both active Skill policies. With skillPolicy: "auto_discover", skill_search, skill_describe, and skill_read_file can access the full readable Skill catalog. With skillPolicy: "pinned_only", those Skill tools are restricted to the attached set. Full instructions load on demand through skill_describe; attaching a Skill never eagerly injects its full instructions. skillPolicy: "none" continues to disable Skill tools and discovery.
selectedActions remain explicit Plan & Execute pins. They can coexist with additional agentTools and with toolPolicy: "auto_discover"; selecting or removing an action does not replace an explicit node policy. Each selected action may carry its own writePolicy (allow, require_approval, or deny) in-app. External authors should omit that field to inherit the catalog default or use an accepted stricter override.
Conversational Agent nodes declare pins in agentTools. Do not combine toolPolicy: "auto_discover" with a non-empty selectedActions array on AI Respond: selectedActions is legacy pinned-only state there, so the external API rejects that contradictory shape instead of letting persistence silently change the policy. Use selectedActions only on node types whose live catalog advertises it, such as Action or AI Plan & Execute.
With pinned_only or auto_discover, every explicit pinned tool must be visible in the live catalog returned for the connection owner:
- Every Erstan
er_*binding must explicitly setsource: "erstan"; Erstan source is never inferred. The name must be catalog-visible. Hidden/internal names, includinger_agent_builder_*, are denied even when disguised with function prefixes, aliases, nestedselectedActions, ortoolKeys. - Connector source names, tool names, and explicit
connectionIdvalues must all be visible to the connection owner in the current workspace. - Within one node, normally pin each canonical runtime tool name once. The only accepted duplicate is one
agentToolsoccurrence mirrored by one legacyselectedActionsoccurrence with the same trimmed/lowercased exact raw identity, the same explicit normalized source, and no conflictingconnectionId(identical when both are set). Function prefixes are not ignored for compatibility:functions.fooandfooare different raw aliases. Duplicates within either array, different raw aliases that canonicalize to one runtime name, conflicting connections, and different sources are rejected. Source conflicts usepinned_tool_runtime_name_source_conflict; all other incompatible duplicates usepinned_tool_runtime_name_duplicate_conflict. - The runtime-owned Tool Hub and skill meta names
tool_search,catalog_search,tool_describe,tool_invoke,tool_batch_invoke,skill_search,skill_describe,skill_read_file, andskill_executecannot be externally pinned under any connector source. Validation returnspinned_tool_runtime_name_reservedbefore consulting the connector catalog. providerToolsis unavailable for external authoring at both node and nested-input level. Use validatedagentToolsbindings on conversational Agents, orselectedActionsonly on node types whose live catalog advertises that field.- Both
actionCategory: "http"and the integration aliaswebhook_outboundare raw HTTP actions and are denied. - If supplied, a pinned tool’s
writePolicymay berequire_approvalordeny. External authoring cannot introducewritePolicy: "allow", automatic-write flags, orautoApproveWrites. An update or publish may preserve an identical existingallowbinding configured in Erstan, but cannot add, move, or duplicate one.
get_agent_node_catalog with includeActionTypes: true when selecting an action node. Do not invent an actionType that is absent from its bounded response.
Canonical graph fields
node.type and data.nodeType must resolve to the same canonical node type. For direct action nodes, actionType is authoritative: a legacy selectedTool value cannot override it or name a hidden tool. Hidden node types, deprecated group containers, unknown action types, and invalid graph shapes are also rejected.
Aliases returned by the node catalog may be accepted as input, but they are canonicalized before persistence. Subsequent get_agent responses return the canonical node.type and matching canonical data.nodeType when that field is present.
Child agent references
Anai-agent node uses targetWorkflowId to invoke another saved agent. The referenced child must be currently readable by the connection owner and belong to the same workspace as the parent. Self-reference is denied.
For a public or automated parent run, Erstan executes the retained published child snapshot. A newer child draft is not exposed to that run, and a child with no published version cannot be invoked from that surface. Test child changes as appropriate, then publish the validated revision in the app or with publish_agent before relying on it from an external or automated parent.
Resource limits
Limits are checked before persistence or connector-catalog loading:validate_agent returns at most 200 normal diagnostics plus a final diagnostics_truncated marker when more problems exist.
Published agents and drafts
Updating a live agent does not replace its public version. Erstan preserves the last published snapshot for normalagents:list and agents:run calls while the newer draft is edited. Draft nodes and prompts are not exposed to public runs until the exact validated revision is published in the app or through publish_agent.
After an agent has ever been published, its MCP metadata is immutable: name, description, category, tags, difficulty, estimatedTime, and behaviorType cannot be changed externally. update_agent accepts graph-only nodes and/or edges changes, atomically forks a draft when necessary, and returns a fresh revision. Make metadata changes in the Erstan app; validate and publish graph drafts with the guarded MCP flow above.
Stale or malformed revisions fail with validation_failed and an agent_revision_conflict or agent_revision_invalid message. Re-read with get_agent instead of retrying with the stale token. Published metadata changes fail with agent_published_metadata_immutable.
Inaccessible or cross-workspace teams and agents return not_found without revealing whether the target exists.
Next steps
Connect an MCP client
Install the plugin and authorize Build access.
Agent Builder
Review and edit the generated graph in Erstan.
Preview, publish & versions
Test and publish the draft when it is ready.
API keys
Scope and permission details.