Core Specificationv3.1

The Neural Protocol

How Cortex speaks to the outside world. A guide to the security, data format, and handshake mechanisms that power the plugin ecosystem.

1The Conceptual Model

Cortex plugins are stateless web servers. Think of them as "Action Libraries" that the AI consults.

When a user says "Check my order #123", the AI doesn't know how to do that. It looks at your Manifest, sees a check_order tool, and sends a request to your server.

1. User Input"Check order status"
2. Cortex EngineCalls Plugin URL
3. Your PluginReturns JSON data

2Security & Authentication

Cortex supports two security models. Choose the one that fits your use case.

The "Shared Secret" Model

Use this when you can identify the user implicitly (e.g. by their stable Cortex ID) or don't need user-specific data.

Best Use Cases

  • Anonymous/Public Tools"Get price of Bitcoin", "Search Knowledge Base". No user identity needed.
  • Order Status (via Input)"Check order #123". The user provides the ID in the prompt. You verify the signature.
  • Sticky ProfilesStore preferences against the stable user.id (e.g. "User prefers Spanish").
Privacy by Design: Cortex does NOT send the user's phone number or name to plugins. You receive a cryptographic hash (user.id) unique to your plugin installation.
javascript
import express from "express";
import { createHmac } from "crypto";

const app = express();
app.use(express.json());

// MIDDLEWARE: Verify the signature
// This proves the request came from Cortex
const verifySignature = (req, res, next) => {
  const authHeader = req.headers["authorization"];
  if (!authHeader) return res.status(401).json({ error: "Missing auth" });
  
  const token = authHeader.split(" ")[1]; // Remove "Bearer "
  const [payloadBase64, signature] = token.split(".");

  // 1. Re-calculate signature with your SHARED SECRET
  // (Env var: PLUGIN_SECRET)
  const expectedSig = createHmac("sha256", process.env.PLUGIN_SECRET)
    .update(payloadBase64)
    .digest("base64url");

  // 2. Compare safely
  if (signature !== expectedSig) {
    return res.status(403).json({ error: "Invalid signature" });
  }
  
  // 3. Decode context (contains hashed user.id)
  const contextJson = Buffer.from(payloadBase64, "base64url").toString();
  req.cortexContext = JSON.parse(contextJson);
  next();
};

app.post("/webhook/orders", verifySignature, (req, res) => {
  // We TRUST this request came from Cortex.
  // The user provided their Order ID in the input.
  const { orderId } = req.body.input;
  
  // We can also store prefs against the anonymous user.id
  const { user } = req.cortexContext;
  console.log("Request from anonymous user:", user.id);
  
  const order = db.findOrder(orderId);
  res.json({ order });
});

3Context: The Source of Truth

Cortex doesn't just send the user's message. It injects a comprehensive Context Object into every request. This keeps your plugin stateless.

json
{
  "serviceName": "CRM_INTEGRATION",
  "organizationId": "org_827393",
  
  // THE IDENTITY
  "user": {
    "id": "u_99283...",     // Hashed, stable User ID
    "hashVersion": 1
  },

  // THE SECRETS
  "config": {
    "apiKey": "sk_live_...", // Decrypted!
    "environment": "production"
  },

  // THE OAUTH TOKEN (If applicable)
  // This is what you use to authorize upstream API calls
  "userAccessToken": "ya29.a0Ad5..."
}

Field-by-Field Breakdown

serviceName
The name of your plugin (e.g. 'HUB_SPOT')
organizationId
The ID of the company running the bot
user.id
A privacy-preserving HASH of the user's phone number + your service ID. Unique to your plugin.
config
Decrypted secrets (API Keys) that the admin configured in the Dashboard.
userAccessToken
If using OAuth, this is the user's specific access token (e.g. for their Gmail).