Octopus
Procedure Storage
Procedures are stored in the Octopus_Procedures SQL table, with steps stored as a JSON column. The schema supports both admin-defined and auto-captured procedures with an approval workflow.
SQL Schema
CREATE TABLE Octopus_Procedures (
Id UNIQUEIDENTIFIER NOT NULL PRIMARY KEY DEFAULT NEWSEQUENTIALID(),
Name NVARCHAR(200) NOT NULL,
Description NVARCHAR(1000) NULL,
TriggerPattern NVARCHAR(500) NOT NULL, -- pattern for matching
StepsJson NVARCHAR(MAX) NOT NULL, -- JSON array of ProcedureStep
AgentId UNIQUEIDENTIFIER NULL, -- NULL = shared across all agents in tenant
TenantId NVARCHAR(100) NOT NULL,
IsApproved BIT NOT NULL DEFAULT 0,
IsShared BIT NOT NULL DEFAULT 0,
IsActive BIT NOT NULL DEFAULT 1,
CreatedBy NVARCHAR(100) NOT NULL, -- 'admin' or 'agent'
ApprovedBy NVARCHAR(200) NULL,
ApprovedAt DATETIMEOFFSET NULL,
CreatedAt DATETIMEOFFSET NOT NULL DEFAULT SYSUTCDATETIME(),
UpdatedAt DATETIMEOFFSET NOT NULL DEFAULT SYSUTCDATETIME()
);
CREATE INDEX IX_Procedures_Agent ON Octopus_Procedures (TenantId, AgentId, IsApproved, IsActive);
Procedure Step JSON Schema
// StepsJson is an array of ProcedureStep objects:
[
{
"order": 1,
"instruction": "Collect vendor name and contact from the user.",
"toolName": null,
"toolArgumentTemplate": null,
"condition": null,
"isOptional": false
},
{
"order": 2,
"instruction": "Look up the vendor in the system.",
"toolName": "vendor_lookup",
"toolArgumentTemplate": "{\"name\": \"{{vendor_name}}\"}",
"condition": null,
"isOptional": false
},
{
"order": 3,
"instruction": "Confirm creation to the user.",
"toolName": "vendor_create",
"toolArgumentTemplate": "{\"name\":\"{{vendor_name}}\",\"contact\":\"{{contact}}\"}",
"condition": "vendor_lookup.result == null",
"isOptional": false
}
]
EF Core Mapping
modelBuilder.Entity<ProcedureEntity>(e =>
{
e.ToTable("Octopus_Procedures");
e.HasKey(x => x.Id);
e.Property(x => x.TenantId).IsRequired().HasMaxLength(100);
e.Property(x => x.Name).IsRequired().HasMaxLength(200);
e.Property(x => x.TriggerPattern).IsRequired().HasMaxLength(500);
e.Property(x => x.StepsJson).HasColumnType("nvarchar(max)");
// Global query filter: only approved, active procedures are visible by default
e.HasQueryFilter(x => x.IsApproved && x.IsActive && x.TenantId == _tenantId);
});
Approval Filter
The global query filter on IsApproved means unapproved candidate procedures do not appear in agent runtime queries. They are only visible in the admin Skill Library UI, which bypasses the filter using IgnoreQueryFilters().