Explicit Action Type Inputs Design
Date: 2026-10-06 Status: Approved (pending spec review)
Goal
Make declared inputs the only way data reaches an Action Type, for both script and AI agent execution modes. Remove the ambient placeholders, environment variables and system-prompt content that implicitly inject subject and event data. Every data dependency of an action becomes visible in its declaration and explicitly mapped on the workflow node that uses it.
Background
Placeholders such as {{ref}} existed because the (now removed) AI Manager invoked action types with no declared
inputs. Action types now run only from workflow action nodes, which declare inputs and outputs. Today data still
reaches actions through four channels:
- Template placeholders: prompt
{{actionType}},{{ref}},{{repository}},{{subjectName}},{{workDir}},{{input}}; script{{subjectId}},{{eventId}},{{taskId}},{{ref}},{{repository}},{{subjectName}},{{apiBaseUrl}},{{workDir}}(ActionTypeValidatorrecognized sets;TaskExecutionService.resolvePromptTemplate;ScriptExecutionService.substitutePlaceholders). - Script environment variables
AXIOM_SUBJECT_ID,AXIOM_EVENT_ID,AXIOM_REF,AXIOM_REPOSITORY,AXIOM_SUBJECT_NAME(always set, whether or not placeholders are used). - The agent system prompt (
TaskExecutionService.buildSystemPrompt) always includes subject name, ref, body and action type name. - Declared inputs via
{{inputs.X}}.
Only channel 4 is declared and visible. The Configuration Assistant, following our own examples, produced action
types with "inputs": [] that silently depend on channels 1–2, which fail at runtime (not validation) when the
subject is not what the action assumes, and cannot be reused on a different target.
Non-Goals
- Changes to output handling (the auto-appended output contract stays as is).
- Changes to human-task nodes,
sdk:action nodes, or tool definitions (tool templates keep their own parameter substitution). - Backward compatibility (pre-1.0; the single baseline schema and seed data are edited in place).
Design
1. Declared inputs are the only template data channel
- In both
promptTemplateandscriptTemplate, the only placeholder is{{inputs.X}}, whereXis a declared input of the action type. - Removed placeholders:
{{input}},{{ref}},{{repository}},{{subjectName}},{{subjectId}},{{eventId}},{{actionType}},{{workDir}},{{apiBaseUrl}},{{taskId}}. ActionTypeValidatorerrors on:- any
{{…}}placeholder other than{{inputs.X}}, with a message naming the replacement:- data (
ref,repository,subjectName,subjectId,eventId): "Declare an input<name>and map it fromcontext.<name>on the workflow node" (eventId→ map fromcontext.event.id); - plumbing in scripts (
workDir,apiBaseUrl,taskId): "Use$AXIOM_WORK_DIR/$AXIOM_API_URL/$AXIOM_TASK_ID"; actionType,input, and plumbing in prompts: "Not available; remove it" (agents already run in the workspace);
- data (
{{inputs.X}}whereXis not a declared input.- Script
{{inputs.X}}keeps its current quote-aware, environment-variable-based substitution (AXIOM_INPUT_X). Prompt{{inputs.X}}keeps inline rendering (InputBindingResolver).
2. Runtime plumbing via environment variables only
- Script processes keep:
AXIOM_API_URL,AXIOM_TASK_ID,AXIOM_WORK_DIR, resolved secrets, the action type'senvironment, and theAXIOM_INPUT_*variables used by script input substitution. - Agent processes never had
AXIOM_API_URL,AXIOM_TASK_IDorAXIOM_WORK_DIR; agents get data only through declared inputs. - Removed from script and agent process environments:
AXIOM_SUBJECT_ID,AXIOM_EVENT_ID,AXIOM_REF,AXIOM_REPOSITORY,AXIOM_SUBJECT_NAME. - The working directory remains the subject workspace (runtime location, not data).
3. Agent prompts
Final prompt sent to the agent = rendered promptTemplate + generated Inputs section + existing output
contract (when outputs are declared).
- Inputs section (new,
InputBindingResolver.buildInputsSection(List<ActionTypeField> inputs, Map<String, Object> values)): heading## Inputs, then one entry per declared input that has a value, in declaration order: name, type, description (if any), and the value. Strings are rendered as-is; numbers and booleans as text; objects and arrays as pretty-printed JSON in a fenced block. All declared inputs with values are listed, including ones also referenced inline (decision B). Omitted when no declared input has a value. - System prompt (
buildSystemPrompt): no subject data. Contains only: the action type name and description, and that the current working directory is the task's workspace. - The automatic output contract (
InputBindingResolver.buildOutputContract) is unchanged.
4. Workflow context and node input mappings
- Every run's initial context contains
subjectId,subjectName,ref,repository(from the subject; empty string when null), pluseventwhen started by an event. All five are protected from being overridden by supplied run inputs (extendPROTECTED_INPUTS). - Node mapping rules for
actionnodes whoseactionTypeis a declared action type (notsdk:): - every required declared input must have a key in the node's
config.inputs→ errorUNMAPPED_REQUIRED_INPUTatcontent.nodes[i].config.inputs; - every key in
config.inputsmust be a declared input → errorUNKNOWN_INPUT_MAPPINGatcontent.nodes[i].config.inputs.<key>; - optional declared inputs may be left unmapped; at runtime they are absent: not listed in the Inputs
section, and
{{inputs.X}}for them renders as an empty string. - Enforced in
ConfigItemValidationService(needs action type declarations, so the context must expose them — see §6) and at publish time via the same shared rule (WorkflowContentRulesgains a check that takes a lookup of action type declarations), and at run time defensively: a task whose required input resolved to nothing fails with a clear message.
5. Updating existing content
- Seed data (
SeedDataInitializer): rewrite seeded action types (e.g.close-subject) to declare inputs. - Assistant: bundled examples (
templates/assistant-reference/examples/) use declared inputs mapped fromcontext.*;AssistantReferenceGeneratordocuments the single placeholder, the plumbing environment variables, the context keys, the mapping rules and the generated Inputs section; the system prompt guidance adds "declare inputs for everything an action operates on" and "do not write your own output-format instructions — Axiom appends them". - AI helpers (
ActionTypeAiService,ScriptAiService) prompt text updated to the new model. - UI: placeholder autocomplete (
PlaceholderCompletionProvider) offers only{{inputs.X}}for the action type's declared inputs (and the plumbing env vars in script mode). - Docs: user guide (action types, workflows) and developer guide updated.
6. Validation context
ValidationContext gains action type declarations (name → declared input names and required flags) from the
database and the pending pack/session, so workflow mapping rules can be checked before Apply. Publish-time
checking reads declarations from the database.
Testing
ActionTypeValidator: each removed placeholder is rejected with its replacement hint; undeclared{{inputs.X}}rejected; declared{{inputs.X}}accepted.- Workflow validation: unmapped required input →
UNMAPPED_REQUIRED_INPUT; unknown mapping key →UNKNOWN_INPUT_MAPPING; unmapped optional input accepted; same results at publish time. - Agent prompt: contains the rendered template, an Inputs section listing all valued inputs (including inline- referenced ones), and the output contract; object values rendered as JSON; unmapped optional inputs absent; system prompt contains no subject name, ref or body.
- Script execution:
AXIOM_REF,AXIOM_REPOSITORY,AXIOM_SUBJECT_NAME,AXIOM_SUBJECT_ID,AXIOM_EVENT_IDabsent from the environment;AXIOM_API_URL,AXIOM_TASK_ID,AXIOM_WORK_DIRpresent;{{inputs.X}}substitution still shell-safe. - Run context contains
repositoryandsubjectName; supplied inputs cannot override any of the five protected keys. - Assistant examples still validate with no errors and apply end to end; seeded action types validate.