Agentic Sessions

Stateful, iterative execution modes for complex tasks requiring tool usage, planning, and memory.

Overview

While LLMAgent provides the raw capability to communicate with language models, Agentic Sessions provide the scaffolding for multi-turn workflows. These sessions maintain state, handle tool execution loops, and manage the lifecycle of a complex task from initial prompt to final answer.

There are two primary session types available, each catering to different architectural needs:

Preparation Phase

Orchestrator skills can define a ##Preparation section in oskill.md to run a pre-context pass before the main session. The preparation phase uses the same tools as the main session, but its output is parsed to extract context variables.

The preparation planner is instructed to emit only lines in the format @context_key := "value". These lines are collected and mapped to @context-piece-* entries that are injected into the main planner prompt or loop system prompt.

LoopAgentSession

LoopAgentSession implements a classic "Thought-Action-Observation" loop (often called ReAct). It is best suited for tasks where the path to the solution isn't known upfront and requires exploration or iterative refinement.

How It Works

  1. Planner Decision: The agent analyzes the history and current context to decide which tool to call next.
  2. Tool Execution: The session executes the chosen tool and captures the output.
  3. Observation: The output is bound to a resultRef identifier and fed back into the context.
  4. Repeat: This cycle continues until the agent calls final_answer or cannot_complete.

Usage

const session = llmAgent.startLoopAgentSession({
    // Tool definitions - parameters come as natural language text
    readFile: {
        description: 'Read a file from disk. Provide the file path as natural text.',
        handler: async (agent, paramsPrompt) => {
            // Parse the natural language parameter to extract the file path
            const filePathMatch = paramsPrompt.match(/file:\s*([^\s]+)/i);
            const filePath = filePathMatch ? filePathMatch[1] : paramsPrompt.trim();
            // Implementation reads the file...
            return fs.readFileSync(filePath, 'utf8');
        }
    },
    webSearch: {
        description: 'Search the web. Provide search terms as natural language.',
        handler: async (agent, paramsPrompt) => {
            // Parse the natural language to extract search query
            const query = paramsPrompt.replace(/^(search for|find|look up)\s*/i, '').trim();
            // Implementation performs web search...
            return performWebSearch(query);
        }
    }
}, "Initial user prompt", {
    maxStepsPerTurn: 10,  // Max tool calls before giving up
    maxErrors: 5,         // Max consecutive errors allowed
    mode: 'fast'          // LLM mode ('fast' or 'deep')
});

// Continue the session with a new prompt
const result = await session.newPrompt("Now summarize the files you found.");
console.log(result); // Final answer string

Key Configuration Options

Reserved Tools

The session automatically injects two control tools:

Tool Result References

Each tool result is stored under a resultRef name like toolName-res-1. When the agent needs to pass a previous tool result as input to another tool, it should reference the value using $$resultRef in the tool prompt. The runtime substitutes $$resultRef with the actual value at execution time.

Example: If a tool produced math-res-1, a follow-up tool call should pass $$math-res-1 in its prompt instead of copying the raw value.

SOPAgenticSession

SOPAgenticSession takes a more structured approach. Instead of deciding one step at a time, it generates a complete execution plan using LightSOPLang. This allows for dependency management, parallel execution (where supported), and clearer inspectability of the agent's intended process.

How It Works

  1. Plan Generation: The agent translates the user's request into a LightSOPLang script (or updates an existing one).
  2. Execution: The LightSOPLangInterpreter executes the script.
  3. Feedback & Refinement: If execution fails (e.g., a variable is missing or a tool fails), the session feeds the error back to the agent to generate a corrected plan.
  4. Result: The final value of the script (usually tagged with @lastAnswer) is returned.

Usage

const session = llmAgent.startSOPLangAgentSession({
    // Skill/Tool descriptions for the planner
    "read-file": "Reads content of a file",
    "summarize-text": "Summarizes text content"
}, "Initial prompt", {
    commandsRegistry: myCommandRegistry, // Maps names to implementations
    planOnly: false,    // Set true to generate plan without executing
    maxPlanAttempts: 3  // Retries for plan correction
});

// Get the generated plan
const plan = await session.getPlan();
console.log(plan);

// Execute a new prompt that might modify the existing plan
const result = await session.newPrompt("Also update the summary with today's date.");

Self-Correction

A powerful feature of SOPAgenticSession is its ability to self-heal. If the generated script fails during execution (e.g., syntax error, invalid argument, or runtime failure), the session captures the error, provides it to the LLM, and requests a rewritten plan. This maxPlanAttempts loop ensures higher reliability for complex workflows.

Preparation APIs

Advanced workflows can call preparation directly via LLMAgent helpers. These APIs return parsed context lines that you can inject into subsequent prompts.

// Loop preparation (ReAct-style)
const prep = await llmAgent.startLoopPreparationSession(tools, preparationText, userPrompt, {
    mode: 'fast',
    maxStepsPerTurn: 20,
    retries: 1
});

// SOP preparation (LightSOPLang)
const prep = await llmAgent.startSOPPreparationSession(skillsDescription, preparationText, userPrompt, {
    mode: 'deep',
    commandsRegistry,
    retries: 1
});

// prep.contextLines -> [ '@context-piece-1 := "..."', ... ]

Choosing the Right Session

Feature LoopAgentSession SOPAgenticSession
Planning Style Step-by-step (ReAct) Upfront Scripting (SOP)
Context Full history of steps Current plan + variables
Best For Exploration, simple tool use Complex workflows, dependency chains
Visibility History log Readable script

Insights

Tool Parameter Design

When using agentic sessions, tool parameters are passed as natural language text strings rather than structured JSON objects or data structures. This design choice prioritizes LLM reliability and ease of response generation over strict type safety.

Why natural language? LLMs are trained extensively on natural language patterns and excel at composing coherent, contextually appropriate text responses. Structured JSON generation can be error-prone, especially with complex nested schemas or when the LLM needs to handle edge cases and variations.

How tools parse structured data: Tools are responsible for parsing the prompt text into structured data using:

This approach makes the system more robust and maintainable, as tool authors can focus on their core functionality while handling parameter parsing at the tool level rather than forcing the LLM to generate perfect JSON every time.