Instructions Guide
View SourceOverview
Instructions are the fundamental unit of execution in the Jido system. An Instruction wraps an action module with its parameters and execution context, allowing Runners to execute them in a standardized way. This guide covers instruction formats, normalization, and best practices.
Instruction Structure
A full instruction struct contains:
%Jido.Instruction{
action: module(), # The action module to execute (required)
params: map(), # Parameters to pass to the action (default: %{})
context: map(), # Execution context data (default: %{})
result: term() # Execution result (default: nil)
}
Instruction Formats
Jido supports several shorthand formats for convenience, all of which are normalized to the full instruction struct during processing. Here are the supported formats:
1. Action Module Only
# Shorthand
MyApp.Actions.ProcessFile
# Normalizes to
%Instruction{
action: MyApp.Actions.ProcessFile,
params: %{},
context: %{}
}
2. Action With Parameters (Tuple Form)
# Shorthand
{MyApp.Actions.ProcessFile, %{path: "/tmp/data.csv"}}
# Normalizes to
%Instruction{
action: MyApp.Actions.ProcessFile,
params: %{path: "/tmp/data.csv"},
context: %{}
}
3. Full Instruction Struct
# Explicit struct
%Instruction{
action: MyApp.Actions.ProcessFile,
params: %{path: "/tmp/data.csv"},
context: %{user_id: "123"}
}
4. Lists of Mixed Formats
# Mixed shorthand list
[
ValidateAction,
{ProcessAction, %{file: "data.csv"}},
%Instruction{action: StoreAction, context: %{store_id: "456"}}
]
# Each element normalizes to a full instruction struct
Normalization Process
All instruction formats are normalized when:
- Planning actions on an Agent
- Directly executing through a Runner
- Creating instruction queues
The normalization ensures:
- Consistent structure for execution
- Parameter validation
- Context preservation
- Type safety
- Serialization support
Best Practices
When to Use Shorthand
Use shorthand formats when:
- Planning simple action sequences
- Writing tests
- Demonstrating examples
- Working with basic workflows
# Good use of shorthand
{:ok, agent} = MyAgent.plan(agent, [
ValidateInput,
{ProcessData, %{format: "csv"}},
StoreResults
])
When to Use Full Structs
Use full instruction structs when:
- Implementing custom runners
- Building complex workflows
- Needing explicit context control
- Working with instruction queues directly
# Good use of full struct
instruction = %Instruction{
action: ProcessData,
params: %{format: "csv"},
context: %{
request_id: "abc123",
user_id: "456",
tenant: "acme"
}
}
Context Management
The context map is preserved during normalization and is available to:
- Action implementations
- Runners
- Error handlers
- Telemetry events
# Setting context during planning
{:ok, agent} = MyAgent.plan(
agent,
ProcessAction,
%{ # Context map
request_id: "abc123",
user_id: "456"
}
)
Working with Instructions Programmatically
When manipulating instructions in code:
# Pattern match on full struct
def process_instruction(%Instruction{action: action, params: params}) do
# Work with normalized form
end
# Transform instructions
def add_context(instructions, context) do
Enum.map(instructions, fn
%Instruction{} = inst ->
%{inst | context: Map.merge(inst.context, context)}
{action, params} ->
%Instruction{action: action, params: params, context: context}
action when is_atom(action) ->
%Instruction{action: action, context: context}
end)
end
Error Handling
Instructions provide rich error context:
case MyAgent.plan(agent, invalid_instruction) do
{:ok, agent} ->
# Success case
{:error, %Error{type: :validation_error, context: context}} ->
# Handle validation failure with full context
end
Testing Instructions
Test both shorthand and normalized forms:
test "supports shorthand planning" do
{:ok, agent} = MyAgent.plan(agent, SimpleAction)
assert [%Instruction{action: SimpleAction}] =
:queue.to_list(agent.pending_instructions)
end
test "preserves context in normalization" do
context = %{request_id: "123"}
{:ok, agent} = MyAgent.plan(agent, SimpleAction, context)
[instruction] = :queue.to_list(agent.pending_instructions)
assert instruction.context.request_id == "123"
end
Summary
- Use shorthand formats for convenience in simple cases
- Work with full instruction structs in implementation code
- Trust the normalization process to handle all formats consistently
- Leverage the context map for cross-cutting concerns
- Test both shorthand and normalized forms
- Handle errors with full context
Remember: Instructions are always normalized before execution, so choose the format that makes your code most readable and maintainable in each specific situation.