Skip to content

Agent Schemas

Agents communicate through structured, versioned JSON. This keeps provider-backed agents interchangeable and makes all outputs auditable.

The core contract is:

AgentContext -> Prompt Builder -> LLM Provider -> AgentResponse

AgentContext

AgentContext is the structured input assembled from EASM platform data before prompt generation.

It should include:

  • organization metadata
  • scan metadata
  • approved scope
  • assets
  • vulnerabilities
  • graph edges
  • scan history
  • previous findings
  • risk statistics

Example:

{
  "organization": {
    "id": "uuid",
    "name": "Example Corp"
  },
  "scan": {
    "id": "uuid",
    "profile": "deep",
    "started_at": "2026-05-31T10:00:00Z",
    "completed_at": "2026-05-31T10:20:00Z"
  },
  "scope": [
    {
      "type": "domain",
      "value": "example.com",
      "approved": true
    }
  ],
  "assets": [
    {
      "id": "uuid",
      "type": "url",
      "value": "https://admin.example.com/login",
      "confidence": 0.98,
      "source_plugin": "httpx",
      "metadata": {
        "status_code": 200,
        "title": "Admin Login"
      }
    }
  ],
  "vulnerabilities": [
    {
      "id": "uuid",
      "asset_id": "uuid",
      "title": "Exposed admin panel",
      "severity": "high",
      "cvss_score": 7.5,
      "risk_score": 8.5,
      "confidence": 0.86,
      "status": "new",
      "source_plugin": "nuclei",
      "evidence": {}
    }
  ],
  "graph": [
    {
      "from": "uuid-domain",
      "to": "uuid-url",
      "relation": "contains"
    }
  ],
  "historical_findings": [],
  "previous_scans": [],
  "statistics": {
    "asset_count": 128,
    "critical_count": 2,
    "high_count": 12,
    "medium_count": 34,
    "recurring_findings": 5
  }
}

Recommended Go shape:

type AgentContext struct {
    Organization       AgentOrganization `json:"organization"`
    Scan               AgentScan         `json:"scan"`
    Scope              []AgentScopeItem  `json:"scope"`
    Assets             []AgentAsset      `json:"assets"`
    Vulnerabilities    []AgentVuln       `json:"vulnerabilities"`
    Graph              []AgentEdge       `json:"graph"`
    HistoricalFindings []AgentVuln       `json:"historical_findings"`
    PreviousScans      []AgentScan       `json:"previous_scans"`
    Statistics         AgentStatistics   `json:"statistics"`
}

AgentContext is transformed into prompts before being sent to the LLM. Large contexts should be reduced, ranked, or summarized while preserving IDs needed for structured output.

AgentResponse

AgentResponse is the structured output contract. It is intended for:

  • OpenAI function calling or structured outputs
  • Claude structured outputs
  • Gemini JSON mode
  • local model adapters

The response must remain machine-readable.

Example:

{
  "agent_type": "risk",
  "category": "advisory",
  "summary": "Risk is concentrated around exposed administrative URLs and recurring high-severity findings.",
  "confidence": 0.91,
  "findings": [
    {
      "asset_id": "uuid",
      "vulnerability_id": "uuid",
      "title": "Exposed administrative entry point",
      "reasoning": "The asset is internet-facing, linked to a high-severity finding, and appears in previous scan history."
    }
  ],
  "actions": [
    {
      "type": "risk_update",
      "asset_id": "uuid",
      "vulnerability_id": "uuid",
      "priority": "high",
      "requires_approval": false,
      "note": "Prioritize remediation due to exposure and recurrence."
    }
  ],
  "recommendations": [
    "Review administrative access controls.",
    "Prioritize exposed high-severity findings before internal-only issues."
  ]
}

Recommended Go shape:

type AgentResponse struct {
    AgentType       string              `json:"agent_type"`
    Category        string              `json:"category"`
    Summary         string              `json:"summary"`
    Confidence      float64             `json:"confidence"`
    Findings        []AgentFinding      `json:"findings"`
    Actions         []AgentAction       `json:"actions"`
    Recommendations []string            `json:"recommendations"`
}

AgentAction

Allowed advisory action types:

Type Meaning Requires Approval
create_note Store analyst-facing note No
report_summary Add text to a report draft No
risk_update Recommend severity, score, or priority changes Policy-dependent
attack_path Store attack path narrative No
false_positive_candidate Mark finding as review candidate Yes by default

Allowed operational action types:

Type Meaning Requires Approval
suggest_scan Recommend a targeted scan Yes
flag_asset Add note/context to an asset Policy-dependent
suggest_profile Recommend a deeper scan profile Yes
suggest_plugin_run Recommend a specific plugin run Yes

Operational suggestion example:

{
  "type": "suggest_scan",
  "plugin": "nuclei",
  "target": "https://admin.example.com",
  "priority": "high",
  "requires_approval": true,
  "note": "Validate the exposed administrative interface with a targeted template set."
}

AgentFinding

AgentFinding captures model reasoning tied to existing platform objects.

{
  "asset_id": "uuid",
  "vulnerability_id": "uuid",
  "title": "Likely recurring exposure",
  "reasoning": "This finding has appeared across multiple scans and affects an internet-facing asset.",
  "confidence": 0.88
}

agent_runs Storage

The initial database schema already contains agent_runs:

CREATE TABLE IF NOT EXISTS agent_runs (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    scan_id UUID REFERENCES scans(id) ON DELETE SET NULL,
    organization_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
    agent_type TEXT NOT NULL,
    status TEXT NOT NULL DEFAULT 'pending',
    input_context JSONB NOT NULL DEFAULT '{}',
    output JSONB NOT NULL DEFAULT '{}',
    actions_taken JSONB NOT NULL DEFAULT '{}',
    notes TEXT NOT NULL DEFAULT '',
    created_at TIMESTAMP NOT NULL DEFAULT NOW(),
    finished_at TIMESTAMP
);

Recommended statuses:

Status Meaning
pending Agent run was created but not started
running Prompt is being built or provider call is in progress
success Agent returned valid structured output
failed Provider failed or returned invalid output
skipped Agent was disabled or policy prevented execution

Validation Rules

Every model response should be validated before it is stored or applied:

  • response must parse as JSON
  • response must match AgentResponse
  • agent_type must match the running agent
  • category must match the registered agent category
  • action type must be known and allowed for the agent
  • operational actions must include requires_approval = true
  • targets must be inside approved scope
  • referenced asset and vulnerability IDs must belong to the same organization
  • confidence must be in range 0..1
  • risk score recommendations must be in range 0..10
  • free-form text must not be treated as executable instructions