Skip to Content

Prompt Management Endpoints

Prompt template management, versioning, lifecycle, and runtime resolution. The agent-config-service runs on port 8010 and is proxied through the API gateway at http://localhost:8000.

Endpoints

MethodPathDescription
GET/prompts/namespacesList namespaces
POST/prompts/namespacesCreate namespace
GET/PUT/prompts/namespaces/{id}Get/update namespace
GET/POST/prompts/namespaces/{id}/tiersList/create budget tiers
PUT/DELETE/prompts/namespaces/{id}/tiers/{tid}Update/delete tier
GET/POST/prompts/templatesList/create templates
GET/PUT/DELETE/prompts/templates/{id}Template CRUD
POST/prompts/templates/{id}/versionsCreate draft
GET/prompts/templates/{id}/my-draftGet user’s draft
PUT/prompts/versions/{id}/save-draftSave draft
DELETE/prompts/versions/{id}/discardDiscard draft
POST/prompts/versions/{id}/promote-pre-prodPromote to pre-prod
POST/prompts/versions/{id}/promote-activePromote to active
POST/prompts/versions/{id}/approveApprove version
POST/prompts/versions/{id}/rejectReject version
GET/prompts/resolve/{ns}:{slug}Resolve prompt (hot path)
POST/prompts/render/{ns}:{slug}Render prompt with variables
GET/prompts/pending-approvalsList pending approvals

GET /prompts/resolve/{namespace}:{slug}

Resolve the best prompt version for a namespace:slug pair. Checks pre-production targeting first, then falls back to active. This is the hot path — results are Redis-cached.

Identity is optional on /resolve and /render (R35 P3b). These two runtime endpoints use get_optional_user, not get_current_user: the tenant always resolves (from X-Tenant-Id, or the canonical default), the user is optional. A call with no user does a tenant-scoped base render (active version, no pre-production targeting); when a real end user is present (X-User-Id header or user_id), pre-prod targeting still applies. This unblocks service-to-service rendering (orchestration renders platform-seeded prompts/context-templates that have no end user) — previously these calls 422’d on the then-required X-User-Id header. The write/admin prompt routes are unchanged and still require a user.

curl -H "Authorization: Bearer $TOKEN" \ "http://localhost:8000/api/v1/prompts/resolve/agents:rule_37_system_prompt?user_id=dev-user"

Response (200):

{ "version_id": "550e8400-e29b-41d4-a716-446655440000", "version_number": 5, "body": "You are the AEGIS Rule 37 Spacing Exception Agent...", "variables_expected": [], "status": "active", "token_estimate": 1847 }

POST /prompts/render/{namespace}:{slug}

Resolve and render a prompt template with Jinja2 variables.

curl -X POST http://localhost:8000/api/v1/prompts/render/agents:rule_37_system_prompt \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "variables": {"well_name": "Smith Ranch #1"}, "user_id": "dev-user" }'

Response (200):

{ "rendered": "You are the AEGIS Rule 37 Spacing Exception Agent...", "token_count": 1823, "version_id": "550e8400-e29b-41d4-a716-446655440000", "version_number": 5, "source": "active" }

POST /prompts/templates/{id}/versions

Create a new draft version for the current user. Returns 409 if a draft already exists.

curl -X POST http://localhost:8000/api/v1/prompts/templates/$TEMPLATE_ID/versions \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "body": "You are a {{ agent_role }} agent...", "change_note": "Add agent_role variable" }'

Response (201):

{ "id": "version-uuid", "version_number": 6, "status": "draft", "body": "You are a {{ agent_role }} agent...", "rendered_token_estimate": 42, "validation_result": { "valid": true, "syntax_ok": true, "subset_ok": true, "injection_scan": {"status": "pass", "findings": []}, "token_estimate": 42, "variables_extracted": ["agent_role"], "unknown_variables": ["agent_role"], "errors": [], "warnings": ["Unknown variables: agent_role"] } }

POST /prompts/versions/{id}/promote-pre-prod

Promote a draft to pre-production. Returns 409 if a pre-prod already exists with conflict resolution options.

curl -X POST http://localhost:8000/api/v1/prompts/versions/$VERSION_ID/promote-pre-prod \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"target_users": ["tester@example.com"]}'

Response (200): Updated version object.

Response (409 — conflict):

{ "conflict": true, "existing_pre_prod": { "version_id": "existing-uuid", "version_number": 3, "author_id": "other-user", "body": "...", "created_at": "2026-04-08T10:00:00Z" }, "options": ["override", "merge"] }

To resolve: call /promote-pre-prod/override or /promote-pre-prod/merge.


POST /prompts/versions/{id}/approve

Approve a pre-production version, activating it. The approver cannot be the version’s author.

curl -X POST http://localhost:8000/api/v1/prompts/versions/$VERSION_ID/approve \ -H "Authorization: Bearer $TOKEN"

Author and approver must be different users. Attempting to approve your own version returns 409.


POST /prompts/audit/verify

Verify HMAC signatures on audit log entries to detect tampering.

curl -X POST "http://localhost:8000/api/v1/prompts/audit/verify?template_id=$TEMPLATE_ID" \ -H "Authorization: Bearer $TOKEN"

Response (200):

{ "total_entries": 47, "verified": 47, "tampered": 0, "tampered_entries": [] }
Last updated on