agentic-control-plane-kit
v0.1.2
Published
Reusable starter kit for adding /manage control-plane API to multi-tenant SaaS platforms
Maintainers
Readme
Echelon — Agentic Control Plane Kit
A reusable starter kit for adding a /manage control-plane API to any multi-tenant SaaS platform. Echelon is the product-shaped CLI and config story on top of this kit; the npm package name remains agentic-control-plane-kit for compatibility.
Overview
This kit provides:
- Spec — Universal contract (request/response envelope, error codes, impact shape, audit). Language-agnostic.
- Kernels — Language-specific implementations that conform to the spec:
- kernel/ (TypeScript) — Node, Supabase Edge, Express, Next.js
- kernel-py/ (Python) — Django, FastAPI (skeleton; implement to pass conformance)
- Packs — Swappable domain modules (IAM, webhooks, settings, billing, domain)
- Bindings — Repo-specific configuration layer
- Conformance Tests — HTTP-based tests; run against any
/manageendpoint
Evaluator start here
If you're reviewing ACP from LinkedIn/GitHub, use this order:
- Public path (preferred): Quickstart — CLI + SDK +
echelon.config.tswithout multi-repo setup. - Manual / advanced embedding: INSTALL.md
- Full multi-repo architecture (maintainers): THREE-REPO-CANONICAL-MODEL.md — internal choreography; not required for app integration.
Supported environments (matrix)
| Topic | Guidance |
|-------|----------|
| Node.js | 20.x required — matches package.json engines.node (CI uses 20). |
| npm | 10.x recommended (packageManager / workflows). |
| Stable / public path | echelon init, echelon protect, echelon audit; SDK defineConfig / protect / createClient / translateConfig. |
| Legacy / compatibility | echelon install (scaffold by framework); manual flow in INSTALL.md. |
| Installer targets | Django, Express, Supabase Edge, hybrid Netlify + Supabase (hybrid_netlify_supabase). |
| @supabase/supabase-js | Optional peer of this package — add it when your adapters or examples use Supabase (INSTALL.md prerequisites). |
Current positioning
ACP now credibly supports a limited, explicit set of SaaS repo shapes, especially Django, Express, Supabase, and hybrid Netlify + Supabase, through tested scaffolding, clearer installer mode contracts, and a more truthful readiness story.
That support is intentionally constrained:
- supported as guided scaffolds for known repo shapes
- suitable for bootstrap and engineer-led installs
- not yet a universal one-click installer for arbitrary repos
- production adoption still requires engineering judgment and adapter completion
Quickstart
Option A: Public product-shell workflow (Recommended)
# Detect project and scaffold readiness workflow
npx --package agentic-control-plane-kit echelon init
# Readiness gate before using connector verbs
npx --package agentic-control-plane-kit echelon protect shopify
npx --package agentic-control-plane-kit echelon auditRequires Node 20+ on the machine running npx (see Supported environments).
The public CLI will:
- auto-detect your framework
- scaffold/init ACP kernel artifacts through a product-facing workflow
- expose guided next steps for protect and audit
- avoid surfacing raw governance or executor wiring in the normal path
Planned / hosted orchestration (currently blocked):
echelon login,echelon link, andechelon envare planned and currently blocked until hosted orchestration exists. They do not persist.echelon/*.jsonstate today.
Legacy / compatibility: echelon install remains the supported scaffold for existing adopters; new projects should prefer echelon init above. Manual embedding (INSTALL.md) is advanced maintenance.
npx --package agentic-control-plane-kit echelon install --framework django
npx --package agentic-control-plane-kit echelon install --framework express
npx --package agentic-control-plane-kit echelon install --framework supabaseinstall remains supported as the compatibility path for current ACP adopters and existing docs.
See installer/README.md for details.
Option B: Manual Installation
See INSTALL.md for manual embedding and advanced setup.
Option C: Programmatic package usage (advanced)
npm install agentic-control-plane-kitDependency note: @supabase/supabase-js is an optional peer dependency. Install it in your project when you implement Supabase-backed adapters, copy Supabase/hybrid installer output, or follow examples that import createClient from @supabase/supabase-js. Purely Django, Prisma, or other DB stacks do not require it.
The package now ships built JavaScript (dist/*.mjs) and type declarations (dist/types/*) for the public entrypoints:
agentic-control-plane-kit(core)agentic-control-plane-kit/sdkagentic-control-plane-kit/packs
For most teams, npx --package agentic-control-plane-kit echelon init is the faster onboarding path.
Public SDK Surface (Product-facing)
For product code (and agents), prefer the stable SDK facade from agentic-control-plane-kit:
defineConfig()(yourechelon.config.tspublic shape)translateConfig()(emit legacy bindings + env + registration metadata from public config)protect()(build a kernel-backed/managerouter from that config)middleware()(thin wrapper for Fetch-style runtimes)createClient()(call/manageactions from a client)
Example (server-side):
import config from './echelon.config';
import { protect } from 'agentic-control-plane-kit';
/**
* Provide your own adapter implementations for your persistence/audit stack.
* (DbAdapter, AuditAdapter, IdempotencyAdapter, RateLimitAdapter, CeilingsAdapter)
*/
const deps = {
dbAdapter: /* your DbAdapter */,
auditAdapter: /* your AuditAdapter */,
idempotencyAdapter: /* your IdempotencyAdapter */,
rateLimitAdapter: /* your RateLimitAdapter */,
ceilingsAdapter: /* your CeilingsAdapter */,
};
export const manageRouter = protect(config, deps);Example (client-side):
import { createClient } from 'agentic-control-plane-kit';
const client = createClient({
endpointUrl: 'https://your-app.com/api/manage',
apiKey: 'ock_...',
});
const res = await client.call('meta.actions');Public config: docs/Echelon-CONFIG-SCHEMA.md.
Bindings → config migration: docs/MIGRATION-CONTROLPLANE-BINDINGS-TO-ECHELON-CONFIG.md.
Compatibility bridge helpers: toBindings(), fromBindings(), and translateConfig() on the public SDK surface.
Legacy note: the sections below document the kernel-first embedding flow. For product/agent code, prefer the stable “Public SDK Surface” above (
defineConfig/protect/createClient). Existing adopters do not need to rewrite immediately:controlplane.bindings.jsonremains supported, andtoBindings()/fromBindings()are the intended migration bridge.
1. (Legacy) Define Your Bindings
Create a bindings.json file:
{
"tenant": {
"table": "brands",
"id_column": "id",
"get_tenant_fn": "get_my_brand_id",
"is_admin_fn": "is_platform_admin"
},
"auth": {
"keys_table": "api_keys",
"key_prefix": "ock_",
"prefix_length": 12,
"key_hash_column": "key_hash",
"key_prefix_column": "prefix",
"scopes_column": "scopes"
},
"database": {
"adapter": "supabase",
"service_role_key": "${SUPABASE_SERVICE_ROLE_KEY}"
}
}2. Implement Adapters
import { Kernel, createSupabaseAdapter } from 'agentic-control-plane-kit';
import { createClient } from '@supabase/supabase-js';
const supabaseAdmin = createClient(SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY);
const dbAdapter = createSupabaseAdapter(supabaseAdmin);
const kernel = new Kernel({
dbAdapter,
bindings: require('./bindings.json'),
packs: ['iam', 'webhooks', 'settings'] // Install packs
});
// Export as edge function or Express middleware
export default kernel.handler;3. Deploy
The kernel exports a standard request handler that works with:
- Supabase Edge Functions
- Vercel Serverless Functions
- Express.js
- Next.js API Routes
- Any Node.js HTTP server
How to Integrate into a Host Repo
Example: Express.js / Next.js API Route
// pages/api/manage.ts (Next.js) or routes/manage.ts (Express)
import { createManageRouter, Pack } from 'agentic-control-plane-kit';
import { iamPack, webhooksPack, settingsPack } from 'agentic-control-plane-kit/packs';
import { createMyDbAdapter } from './adapters/db';
import { createMyAuditAdapter } from './adapters/audit';
import { createMyIdempotencyAdapter } from './adapters/idempotency';
import { createMyRateLimitAdapter } from './adapters/rate-limit';
import { createMyCeilingsAdapter } from './adapters/ceilings';
import bindings from './config/bindings.json';
// Create adapters (implement interfaces from kernel/src/types)
const dbAdapter = createMyDbAdapter();
const auditAdapter = createMyAuditAdapter();
const idempotencyAdapter = createMyIdempotencyAdapter();
const rateLimitAdapter = createMyRateLimitAdapter();
const ceilingsAdapter = createMyCeilingsAdapter();
// Install packs
const packs: Pack[] = [iamPack, webhooksPack, settingsPack];
// Create router
const manageRouter = createManageRouter({
dbAdapter,
auditAdapter,
idempotencyAdapter,
rateLimitAdapter,
ceilingsAdapter,
bindings,
packs
});
// Express handler
export default async function handler(req: Request, res: Response) {
if (req.method !== 'POST') {
return res.status(405).json({ error: 'Method not allowed' });
}
try {
const body = await req.json();
const response = await manageRouter(body, {
request: req,
ipAddress: req.ip || req.headers['x-forwarded-for'],
userAgent: req.headers['user-agent']
});
res.status(response.status || 200).json(JSON.parse(response.body));
} catch (error) {
res.status(500).json({ error: 'Internal server error' });
}
}Example: Supabase Edge Function
// supabase/functions/manage/index.ts
import { createManageRouter, Pack } from 'agentic-control-plane-kit';
import { iamPack, webhooksPack, settingsPack } from 'agentic-control-plane-kit/packs';
import { createSupabaseDbAdapter } from './adapters/supabase-db';
import { createSupabaseAuditAdapter } from './adapters/supabase-audit';
import { createSupabaseIdempotencyAdapter } from './adapters/supabase-idempotency';
import { createSupabaseRateLimitAdapter } from './adapters/supabase-rate-limit';
import { createSupabaseCeilingsAdapter } from './adapters/supabase-ceilings';
import bindings from './config/bindings.json';
import { serve } from 'https://deno.land/[email protected]/http/server.ts';
// Create adapters (adapter-driven, not hardcoded)
const dbAdapter = createSupabaseDbAdapter(Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!);
const auditAdapter = createSupabaseAuditAdapter();
const idempotencyAdapter = createSupabaseIdempotencyAdapter();
const rateLimitAdapter = createSupabaseRateLimitAdapter();
const ceilingsAdapter = createSupabaseCeilingsAdapter();
// Install packs
const packs: Pack[] = [iamPack, webhooksPack, settingsPack];
// Create router
const manageRouter = createManageRouter({
dbAdapter,
auditAdapter,
idempotencyAdapter,
rateLimitAdapter,
ceilingsAdapter,
bindings,
packs
});
// Edge function handler
serve(async (req) => {
if (req.method !== 'POST') {
return new Response(JSON.stringify({ error: 'Method not allowed' }), {
status: 405,
headers: { 'Content-Type': 'application/json' }
});
}
try {
const body = await req.json();
const response = await manageRouter(body, {
request: req,
ipAddress: req.headers.get('x-forwarded-for') || 'unknown',
userAgent: req.headers.get('user-agent') || 'unknown'
});
return new Response(response.body, {
status: response.status || 200,
headers: { 'Content-Type': 'application/json', ...response.headers }
});
} catch (error) {
return new Response(JSON.stringify({ error: 'Internal server error' }), {
status: 500,
headers: { 'Content-Type': 'application/json' }
});
}
});Step 1: Copy the Kit (advanced/manual flow)
# Option A: Install as npm package
npm install agentic-control-plane-kit
# Option B: Copy kernel source into your repo
cp -r node_modules/agentic-control-plane-kit/kernel ./src/manageThis section is for manual/programmatic embedding. For most users, start with npx echelon install.
Step 2: Create Bindings File
Inspect your codebase and create config/bindings.json:
- Tenant model: What table stores tenants? (
brands,orgs,workspaces) - Auth: Where are API keys stored? What's the prefix format?
- Database: What client do you use? (Supabase, Prisma, Drizzle, raw SQL)
Step 3: Implement Adapters
The kit defines interfaces. You implement adapters for your stack:
// For Supabase
import { createSupabaseAdapter } from 'agentic-control-plane-kit/adapters/supabase';
// For Prisma
import { createPrismaAdapter } from 'agentic-control-plane-kit/adapters/prisma';
// Custom adapter
import { DbAdapter } from 'agentic-control-plane-kit/kernel/src/types';
class MyDbAdapter implements DbAdapter { ... }Step 4: Install Packs
Choose which packs to install:
const kernel = new Kernel({
dbAdapter,
bindings,
packs: [
'iam', // Almost always needed
'webhooks', // Almost always needed
'settings', // Common
'billing', // Optional (only if handling payments)
'domain' // Always (repo-specific)
]
});Step 5: Define Domain Actions
Create your repo-specific domain actions:
// packs/domain/actions.ts
export const domainActions = [
{
name: 'domain.shop.products.list',
scope: 'manage.domain',
description: 'List products',
params_schema: { ... }
}
];Step 6: Generate OpenAPI Spec
npm run generate-openapi
# Outputs: public/api/openapi.jsonStep 7: Test
npm run test:invariants
# Runs TS kernel unit tests
npm run test:conformance
# Runs HTTP conformance tests — works against any kernel (TS or Python)
# Set ACP_BASE_URL and ACP_API_KEY to test your deployed /manage endpointArchitecture
One spec, many kernels. No Node sidecar everywhere — use the kernel for your stack.
┌─────────────────────────────────────────────────────────┐
│ Spec (universal) │ Contract, error codes, impact shape, conformance tests
├─────────────────────────────────────────────────────────┤
│ Kernels (language-specific) │ kernel/ (TS), kernel-py/ (Python)
├─────────────────────────────────────────────────────────┤
│ Packs (swappable) │ IAM, webhooks, settings, billing, domain
├─────────────────────────────────────────────────────────┤
│ Bindings (repo-specific) │ Tenant model, DB client, entity names
└─────────────────────────────────────────────────────────┘For Python (Django) clients
Use kernel-py — no Node service required. See kernel-py/README.md and INTEGRATION-GUIDE.md.
For Node/Supabase clients
Use kernel/ (TypeScript).
Documentation
Core Documentation
- INSTALL.md - Complete installation checklist
- INTEGRATION-GUIDE.md - How to integrate with Repo B (Governance Hub)
- SAAS-DEPLOYMENT-GUIDE.md - Deploying ACP in a SaaS project
- KERNEL-ARCHITECTURE.md - Kernel architecture and design
- spec/ACP-SPEC.md - Complete ACP specification
Three-Repo Architecture
- THREE-REPO-CANONICAL-MODEL.md - Canonical architecture model (Repo A, B, C roles and responsibilities)
- MCP-GATEWAY-THREE-REPO-ARCHITECTURE.md - How MCP Gateway fits into three-repo system
MCP Gateway
- MCP-GATEWAY-SUMMARY.md - MCP Gateway implementation summary
- MCP-DEPLOYMENT-GUIDE.md - MCP Gateway deployment guide
- gateway/README.md - Gateway-specific documentation
- docs/MCP-GATEWAY-PLAN.md - Gateway architecture plan
Security
- SECURITY-REVIEW.md - Security review and hardening
- INTERNAL-ENDPOINTS-SECURITY.md - Internal endpoints security model (HMAC auth)
- MCP-SECURITY-RISKS.md - MCP-specific security risks
Governance
- docs/AGENT-GOVERNANCE-GUIDE.md - Agent governance guide
- docs/GOVERNANCE-PACK.md - Governance pack documentation
MCP Registration & Credentials
- MCP-REGISTRATION-AND-CREDENTIAL-STORAGE-IMPLEMENTATION.md - MCP server registration and credential storage
- CONNECTOR-CATALOG-IMPLEMENTATION.md - Connector catalog system
Consumer Product
- CONSUMER-PRODUCT-GUIDE.md - Consumer product guide
- SIGNUP-IMPLEMENTATION-GUIDE.md - Signup flow implementation
- GATEWAY-SIGNUP-ARCHITECTURE.md - Signup architecture
- BILLING-ARCHITECTURE.md - Billing model
For Developers
- spec/README.md - Universal contract (source of truth)
- installer/README.md - Automated installer (Echelon CLI)
- INSTALLER-ARCHITECTURE.md - Installer architecture and design
- kernel-py/README.md - Python kernel (Django/FastAPI)
Real-World Integration Examples
Onsite Affiliate (Supabase)
- ✅ Integrated with Edge Bot as Agent
- ✅ Uses IAM, Webhooks, Settings packs
- ✅ Domain pack:
domain.assets.*,domain.creators.*,domain.orders.*
Lead Scoring SaaS (Django)
- 📋 See INTEGRATION-GUIDE.md for Django integration
- 📋 Domain pack:
domain.leadscoring.models.*,domain.leadscoring.rules.*,domain.leadscoring.scores.*
License
MIT
