Composite identity
Composite identity is an authentication and authorization mechanism that combines two identities into a single token:
- A service account. The agent that performs the actual actions.
- A human user. The person who initiated the request.
Service accounts have a composite identity because a human user initiates the actions they perform. The exception is scheduled triggers, which run with no human user.
Composite identity is automatically included in GitLab Duo Agent Platform.
This dual-identity approach solves a critical challenge: agents need to act with access that does not exceed the access of the user who triggered them, or the access that the service account was granted, while maintaining a distinct identity that clearly shows the action was performed by an agent, not directly by the human user.
Why composite identity matters
The composite identity is important because it helps ensure:
- Traceability: All agent activities are clearly attributed to a service account, making it easy to identify automated actions in audit logs and commit histories.
- Security: The agent can perform actions that only the service account and the triggering user have access to do. This intersectional access prevents privilege escalation.
- Accountability: The human user’s identity is embedded in the token, creating an audit trail that links agent actions back to the person who initiated them.
For example, when you ask an agent to create tests for your code, the resulting commits will show they were created by the service account on your behalf.
Where composite identity is used
Composite identity is used when flows and agents execute on runners. This list includes:
- Foundational flows.
- Custom flows.
- External agents.
- Any flow started through the endpoint
api/v4/ai/duo_workflows/workflows.
Composite identity does not apply to:
- GitLab Duo Agentic Chat in the UI and IDE.
- Flows that a scheduled trigger runs. These flows run as a dedicated service account, and the role of that account is the only limit on what the flow can do. For more information, see service account for scheduled triggers.
How composite identity works
The token that authenticates requests is a composite of two identities:
- Primary author: The human user who started the agent or flow.
The human user’s
idis included in the scopes of the token by using a dynamic scope. - Secondary author: A service account, which is the owner of the token and has the Developer role.
This composite identity ensures that any activities authored by the GitLab Duo Agent Platform are attributed to the human user, while preventing privilege escalation by either the human user or the service account.
Composite identity workflow
The composite identity is part of the workflow.
- Create a flow in the AI Catalog.
- No composite identity-related changes occur.
- Enable the flow for a project.
- A service account is created in the top-level group.
For custom flows, the username is similar to
ai-<flow_name>-<top_level_group_name>. For foundational flows, the username is similar toduo-<flow_name>-<top_level_group_name>. - The service account is added to the project with the Developer role. A foundational flow service account is added to each project that has foundational flows turned on.
- A service account is created in the top-level group.
For custom flows, the username is similar to
- A user executes the flow.
The flow is executed by a one-time composite identity. This identity has a combination of the user’s role and the service account’s Developer role, whichever is more restrictive. So if the user is a Maintainer, but the service account is a Developer, the Developer role is used.
The flow has access to all projects that both:
- The user has access to.
- The service account has been added to.
For example, if the service account has been added to other projects, and the user has access to those projects, the flow can access those projects even if the user has not used the flow there before.
Some users can access every project in a group, like administrators or users with the Owner role for the top-level group. For these users, the projects the service account is a member of set the limit on what the flow can access.
Investigate activity by a service account
Service account membership, sessions, and data access are separate signals. To investigate whether a service account accessed project data, collect evidence for each signal.
Membership
Membership shows that the service account is authorized to access a project, not that the service account accessed the project.
- To check the service account’s membership, view the project members. Use the members list as the authoritative source, because not every foundational flow membership change creates an audit event.
- To check membership history, review the
member_created,member_destroyed, andduo_service_account_provisionedaudit events. - To check when flow triggers were created, changed, or deleted in a project, review the
flow_trigger_created,flow_trigger_updated, andflow_trigger_deletedaudit events. Like membership, these events show configuration changes, not flow runs.
Session
A session shows that a flow used the service account, and which user the run is attributed to.
- Review the sessions for the project, including the user for each session. Sessions are deleted after the session retention period.
- Review the CI/CD job logs for each session. The logs show the commands the flow ran on the runner, including repository checkout.
Data access
Data access shows which requests the composite identity made during a session.
- Review the
api_request_access_with_scopeaudit events. These events record the method and path of REST API requests made with theai_workflowstoken scope. These events cover REST API requests only, not GraphQL requests or Git operations like cloning the repository. These events are user-scoped, so they appear in instance audit events, not group or project audit events. - Review the AI audit events. These events are available only if AI audit event storage was turned on before the session ran.
- Search the API logs for entries that include a
meta.scoped_userfield. This field is present only for requests made with a composite identity, and contains the user the session is attributed to.- On GitLab Self-Managed, search
api_json.log. - On GitLab Dedicated, search the application logs in your Amazon S3 bucket.
- On GitLab Self-Managed, search
Token permissions for AI Catalog flows
AI Catalog flows use different token types with different permission scopes:
- OAuth tokens used for composite identity in AI workflows have access restricted to the
ai_workflowsandmcpscopes. This OAuth token is passed to the AI Gateway to run the flow. - CI job tokens that are triggered as part of the flow have permissions further restricted by the available job token permissions.
Because these are different token types with different scopes, the CI/CD job has different permissions than the OAuth token.
Compliance considerations for merge requests
When a flow creates a merge request, the merge request is attributed to the human user who triggered the flow instead of the service account. This is done to adhere to compliance frameworks that require segregation of duties, including:
- SOC 2 (System and Organization Controls 2)
- SOX (Sarbanes-Oxley Act)
- ISO 27001 (Information Security Management)
- FedRAMP (Federal Risk and Authorization Management Program)
These frameworks typically require that a user cannot author code changes and approve those changes for production deployment.
Understanding the attribution model
Even though the service account creates the commits and opens the merge request, the human user is considered the author because:
- The human user directed the service account to create the changes.
- From a compliance perspective, prompting an AI system to write code is equivalent to writing the code yourself.
- The service account acts as a proxy for the human user’s intent.
This attribution applies to authorship only. It does not determine who is billed for usage.