Portal Community

What Is Procedural Memory?

When an Octopus agent successfully executes a complex multi-step task — such as processing an invoice, onboarding a new employee, or running a diagnostic — the resolved plan can be saved as a procedure. On subsequent requests for the same task, the agent retrieves the stored procedure from Octopus_Procedures and executes its steps directly, bypassing the reasoning phase that deriving the plan would require.

This is analogous to a human expert who, having solved a complex problem once, can repeat the solution efficiently without rethinking from first principles.

Column Reference

ColumnTypeConstraintsDescription
ProcedureIduniqueidentifierPK, NOT NULLGUID primary key.
AgentIduniqueidentifierFK, NOT NULLThe agent that owns this procedure. Agents can only retrieve their own procedures.
TenantIdintNOT NULL, IXMulti-tenancy discriminator.
Namenvarchar(300)NOT NULL, UNIQUE(TenantId, AgentId, Name)Human-readable, semantic name for the procedure. Used by the agent to match incoming requests against stored procedures.
Stepsnvarchar(max)NOT NULLJSON array of step objects defining the procedure. See Steps JSON schema below.
ActivatedAtdatetime2NULLUTC timestamp of the last time this procedure was retrieved and executed. Used by the retention job to identify stale procedures.
CreatedAtdatetime2NOT NULLUTC creation timestamp.

Steps JSON Schema

Each procedure is a JSON array of step objects. The framework supports several step types:

[
  {
    "stepId": 1,
    "type": "sql-query",
    "description": "Fetch the invoice record",
    "params": {
      "datasourceId": "main-db",
      "query": "SELECT * FROM Invoices WHERE InvoiceId = @invoiceId AND TenantId = @tenantId",
      "outputVar": "invoice"
    }
  },
  {
    "stepId": 2,
    "type": "condition",
    "description": "Check invoice status",
    "params": {
      "expression": "invoice.Status == 'Pending'",
      "onTrue": 3,
      "onFalse": 6
    }
  },
  {
    "stepId": 3,
    "type": "workflow-trigger",
    "description": "Trigger the invoice approval workflow",
    "params": {
      "workflowId": "invoice-approval-v2",
      "inputs": { "invoiceId": "@invoiceId" }
    }
  },
  {
    "stepId": 4,
    "type": "agent-message",
    "description": "Notify user of outcome",
    "params": {
      "message": "Invoice {{invoiceId}} has been submitted for approval."
    }
  }
]

Step Types

TypeDescriptionKey Params
sql-queryExecute a parameterized SQL SELECT and store the result in an output variabledatasourceId, query, outputVar
sql-updateExecute a parameterized INSERT/UPDATE/DELETEdatasourceId, command
workflow-triggerFire a Flow Studio workflow with inputsworkflowId, inputs
agent-messageSend a message to the user in the conversationmessage (template string)
conditionBranch execution based on an expression resultexpression, onTrue (stepId), onFalse (stepId)
tool-callCall a registered plugin tool directlypluginId, toolName, arguments
loopRepeat a sub-procedure for each item in a collectioncollection, stepIds

How Agents Retrieve Procedures

When the agent receives a user request, it performs a two-stage lookup:

1

Exact Name Match

The agent extracts the likely task name from the user message using keyword extraction and queries Octopus_Procedures WHERE Name = @extractedName AND AgentId = @agentId AND TenantId = @tenantId.

2

Semantic Match (Fallback)

If no exact match is found, procedure names are embedded and compared semantically against the user's request using the vector store. The closest matching procedure above the confidence threshold is used.

3

Fresh Derivation (Final Fallback)

If no procedure matches with sufficient confidence, the agent derives the plan fresh from the LLM and optionally saves the derived plan as a new procedure for future use.

Common Queries

-- All procedures for an agent
SELECT ProcedureId, Name, ActivatedAt, CreatedAt
FROM Octopus_Procedures
WHERE TenantId = @tenantId
  AND AgentId = @agentId
ORDER BY Name;

-- Stale procedures (not used in 90 days)
SELECT ProcedureId, Name, ActivatedAt
FROM Octopus_Procedures
WHERE TenantId = @tenantId
  AND (ActivatedAt IS NULL OR ActivatedAt < DATEADD(DAY, -90, GETUTCDATE()))
ORDER BY ActivatedAt;

-- Retrieve a specific procedure by name for execution
SELECT ProcedureId, Name, Steps
FROM Octopus_Procedures
WHERE TenantId = @tenantId
  AND AgentId = @agentId
  AND Name = @procedureName;
Procedures Are an AI Learning Asset

A well-populated Octopus_Procedures table represents accumulated organizational knowledge. Agents that have solved common problems store those solutions here, progressively becoming faster and more deterministic for routine tasks. Backing up and exporting procedure data as part of your DR strategy ensures this knowledge is not lost.