Add External Session API
What does this MR do and why?
Implements the external agent session API.
When a developer runs Claude Code or OpenCode against a GitLab project, glab calls this API to create and complete session records in GitLab. Each session captures the agent type, identity, and sync method, providing the foundation for per-turn audit event attribution.
Sessions are stored in duo_workflows_workflows using environment: :external, giving sessions immediate access to the existing Sessions UI, the AiAuditEvent audit report, and the ClickHouse write path.
How to set up and validate locally
Prerequisites
- GDK running with an Ultimate license
- Feature flag enabled:
Feature.enable(:ai_agent_session_tracking) duo_external_agents_enabled=> true- An ai_agent_identities record exists (create via the registration API or console)
Create Session
curl -X POST "http://gitlab.localdev:3000/api/v4/projects/1/ai_agent/sessions" \
-H "PRIVATE-TOKEN: <your-pat>" \
-H "Content-Type: application/json" \
-d '{
"agent_type": "claude-code",
"agent_identity_id": 1,
"sync_type": "hook"
}'
# Expected: 201 with session JSON, status: "running"Idempotency
curl -X POST "http://gitlab.localdev:3000/api/v4/projects/1/ai_agent/sessions" \
-H "PRIVATE-TOKEN: <your-pat>" \
-H "Content-Type: application/json" \
-d '{
"agent_type": "claude-code",
"agent_identity_id": 1,
"sync_type": "hook",
"idempotency_key": "test-uuid-123"
}'
# Expected: 201 with same id on repeat callsComplete Session
curl -X PATCH "http://gitlab.localdev:3000/api/v4/projects/1/ai_agent/sessions/<session_id>" \
-H "PRIVATE-TOKEN: <your-pat>" \
-H "Content-Type: application/json" \
-d '{
"status": "completed",
"jsonl_sha256": "a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3"
}'
# Expected: 200 with status: "finished"List Sessions
curl "http://gitlab.localdev:3000/api/v4/projects/1/ai_agent/sessions" \
-H "PRIVATE-TOKEN: <your-pat>"
# Expected: 200 with array of sessionsDatabase
scope :external query plan
Query:
SELECT "duo_workflows_workflows".*
FROM "duo_workflows_workflows"
WHERE "duo_workflows_workflows"."environment" = 6
AND "duo_workflows_workflows"."project_id" = $1
ORDER BY "duo_workflows_workflows"."id" DESC
LIMIT 20Execution plan:
Limit (cost=2.18..2.18 rows=1 width=520) (actual time=0.041..0.042 rows=5 loops=1)
-> Sort (cost=2.18..2.18 rows=1 width=520) (actual time=0.040..0.041 rows=5 loops=1)
Sort Key: id DESC
Sort Method: quicksort Memory: 26kB
-> Index Scan using index_duo_workflows_workflows_on_project_id on duo_workflows_workflows (cost=0.14..2.17 rows=1 width=520) (actual time=0.018..0.027 rows=5 loops=1)
Index Cond: (project_id = 1)
Filter: (environment = 6)
Planning Time: 4.204 ms
Execution Time: 0.060 msUses existing index_duo_workflows_workflows_on_project_id. No new index required.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.
Related to #603150