Skip to content

Agent Script Steps

A Script step runs a Python script from one of the agent’s attached skills. No model is involved unless the script asks for one: the step runs the script in the agent’s sandbox, reads the result the script declares, and moves the run on. Use it for work that should happen the same way every time, such as syncing records, transforming a webhook payload, or calling an integration in a loop.

  1. In the agent builder, select + under Agent Steps, then Add Script step.

  2. Pick the Skill. The list shows the skills attached to this agent. If you may attach skills, your own library appears too, and choosing one of those attaches it when you save.

  3. Pick the Script: a .py file inside the skill package. The editor previews the file.

  4. Set the Timeout and the Agent follow-up toggle, then save.

SettingWhat it does
SkillThe attached skill the script comes from. The step runs the skill’s latest version, and the run records the exact content that ran.
ScriptA relative .py path inside the skill package. Python is the only supported language.
ToolsRead-only. Scripts run with the tool servers enabled in the agent’s Tools section.
Timeout (seconds)Wall-clock limit for the script, from 1 to 900 seconds. Defaults to 120.
Agent follow-upLets the script hand its result to the agent for a model turn. Off by default. See Agent follow-up.

A skill that a Script step runs cannot be detached from the agent until the step is removed or pointed at another skill. The agent’s organization needs a default chat model even with Agent follow-up off; without one the step fails before the script starts. A Script step never retries: scripts can call tools with side effects, so a step that fails is reported, not run again.

  • Kindo runs python3 <script path> in a fresh working directory inside the run’s sandbox. The skill’s files are staged at their package-relative paths, so a script can import its sibling modules.
  • Only text files in the skill package are staged. Binary files are skipped.
  • The kindo_script helper module is importable from any staged path. Only the Python standard library is guaranteed to be installed.
  • Network access follows your organization’s Sandbox Network Access setting. See Tool Actions and Permissions.
  • A script still running when the timeout expires is killed.
  • Files the script writes outside its working directory stay in the run’s sandbox for the rest of the run, so later steps that use the sandbox can read them.
import kindo_script
payload = kindo_script.read_input()["payload"]

read_input() returns a dictionary with at least a payload key, or None when the input is unavailable. Ignore keys you do not recognize; new ones may be added.

How the run startedpayload
Integration Event triggerThe event body Kindo received.
Direct Webhook URL triggerThe request body.
Started by a parent agent, or from a chatThe text the parent forwarded, as a string.
Run manually, on a schedule, or through the APInull. Input values sent through the API are agent inputs, not the script payload.

When the Script step is the first step of the run, the trigger payload or the parent’s context is also placed in the conversation as context for later steps.

import kindo_script
kindo_script.declare_result("success", detail="Synced 12 records.")

Call declare_result before the script exits. The last call wins. A script that exits with code 0 without declaring anything is a success.

ArgumentTypeMeaning
status"success" or "error"The outcome. A declared error completes the step; it is an outcome, not a failure.
detailstringFree text describing the outcome. Shown in the run and passed to the agent on follow-up.
guidancestring, optionalSteering for the agent’s follow-up turn.
inferboolean, default FalseAsk the agent to follow up on the result. Honored only when Agent follow-up is on.
halt_runboolean, default FalseCancel the run once this step completes. Later steps never run.

declare_result raises ValueError for a status other than success or error, and TypeError when infer or halt_run is not a boolean.

Kindo keeps the last 8,192 characters of detail and of guidance. A longer value loses its beginning, and a leading marks that this happened. Only the truncated text is stored. Write a summary, or a pointer to output stored elsewhere, rather than a full log.

What the script didStatusDetail
Declared a valid result, with any exit codeAs declaredAs declared
Declared nothing and exited 0successstdout
Declared nothing and exited non-zeroerrorstderr, then stdout, then “Script failed without output.”
Wrote a result Kindo could not parseerrorstderr, then stdout, then “Script failed without output.”
Was killed at the timeouterror”Script exceeded its time limit.” followed by the end of stderr or stdout

A timeout is an error whatever the script declared. Undeclared infer and halt_run are False. Write diagnostics to stderr: it is what becomes the detail when a script fails without declaring one, and a Python traceback lands there on its own.

With Agent follow-up on, a script that declares infer=True hands its result to the agent. The agent receives the declared status, detail, and guidance, along with every tool call the script made, and runs a model turn with the agent’s tools on your organization’s default chat model. The model’s reply becomes the step’s response. With the toggle off, infer=True is ignored and the step completes with the declared result.

kindo_script.declare_result(
"error",
infer=True,
detail="Upstream returned 404 for 3 of 12 records.",
guidance="Retry the failed records with the fallback endpoint.",
)

A script that declares halt_run=True completes its step and then cancels the run. Steps after it never run, and the run shows a Run halted marker. Declared together with infer=True, the follow-up turn runs first, then the run halts.

For objective evaluation, a Script step’s verdict follows its status: success is satisfied and error is not satisfied. Because halt_run cancels the run, a run halted by a script reports an aggregate result of partial on the Agents API, with the per-step verdicts intact.

Scripts use the sandbox tool channel, the same one shell commands use: the kindo_tool module and the kindo-tool CLI, with the same stderr rule, the same ceiling of 100 calls, counted per step run, and the same rule that only tools set to run automatically are callable. Script steps always have the channel and need no separate enrollment in its rollout. Three things differ for Script steps:

  • The tool set comes from the tool servers enabled in the agent’s Tools section rather than from the conversation.
  • The channel stays open for the whole script run, bounded by the step’s timeout rather than by a single command’s.
  • Each call is recorded in the run as its own entry beside the script’s execution, as well as in the audit log.
import kindo_tool
issues = kindo_tool.call_tool("linear_list_issues", {"teamId": "ENG"})

Each Script step adds two messages to the run’s conversation: a message naming the skill and script, and a response holding the execution. The execution shows the declared fields under RESULT and the free text under DETAIL. Each tool call the script made appears alongside it.

  • A run stopped while a script is running kills the script. The response is marked Generation Stopped, and the execution reads “Tool execution was interrupted before completion”.
  • Version history captures the skill, script path, timeout, and Agent follow-up setting. Duplicating or restoring an agent keeps its Script steps. Importing an agent definition attaches each pinned skill to the new agent, and is refused when the importer cannot see that skill, which includes every skill from another organization.