Create API keys for Elastic Agent Builder
Use an API key to authenticate applications that call Elastic Agent Builder programmatically, including custom clients, scripts that use curl, MCP clients, and A2A clients.
API keys use the same Kibana feature privileges as roles. The role management UI displays names such as Agent Builder: Read, while an API key role descriptor uses the corresponding application privilege name, such as feature_agentBuilder.read.
Before creating an API key:
Make sure the user creating the key has the
manage_api_keyormanage_own_api_keycluster privilege.Create the key as a user, not by authenticating the request with another API key. An API key can create only a derived key with no privileges.
Make sure the user creating the key has every privilege that you assign to the key. An API key cannot grant more privileges than its owner has.
Identify the Kibana space that the client will access. The examples use the default space.
Identify the index patterns that agents and tools need to query. Replace
customer-*in the examples with your own patterns.Determine whether agents use Elasticsearch inference endpoints, Kibana connectors, or workflows. These features require additional privileges.
Refer to the privilege reference for the exact privilege names to use in a role descriptor.
If you're using
curl, set the Elasticsearch URL, Kibana URL, and username:export ELASTICSEARCH_URL="https://<elasticsearch-host>" export KIBANA_URL="https://<kibana-host>" export ELASTIC_USERNAME="<username>"- Use
ELASTICSEARCH_URLto create API keys with the Elasticsearch/_security/api_keyAPI. To locate it, refer to Find your Elasticsearch endpoint. - Use
KIBANA_URLto call the Elastic Agent Builder APIs under/api/agent_builder. ELASTIC_USERNAMEis the username of the user creating the key. Thecurlexamples prompt you for this user's password.
- Use
The following example creates a key for a client that can use agents and view Elastic Agent Builder components, but cannot create, update, or delete them. The key can read data only from indices matching customer-*.
Run the following request in Console. The key is owned by the user who is signed in to Kibana:
POST /_security/api_key
{
"name": "agent-builder-read-only",
"expiration": "30d",
"role_descriptors": {
"agent-builder-read-only": {
"cluster": ["monitor_inference"],
"indices": [
{
"names": ["customer-*"],
"privileges": ["read", "view_index_metadata"]
}
],
"applications": [
{
"application": "kibana-.kibana",
"privileges": [
"feature_agentBuilder.read",
"feature_actions.read",
"feature_workflowsManagement.read"
],
"resources": ["space:default"]
}
]
}
}
}
monitor_inferenceis required when agents or tools call the Elasticsearch Inference API. Remove it if they do not.- Replace
customer-*with the index patterns that the client needs. The assigned index privileges allow reads and access to index mappings, but not writes. - Use
kibana-.kibanaas the application name for Kibana feature privileges. feature_agentBuilder.readprovides read-only access to Elastic Agent Builder. The other two privileges provide read-only access to connectors and workflows.- Replace
space:defaultif the client uses a different Kibana space.
curl --user "${ELASTIC_USERNAME}" \
-X POST "${ELASTICSEARCH_URL}/_security/api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "agent-builder-read-only",
"expiration": "30d",
"role_descriptors": {
"agent-builder-read-only": {
"cluster": ["monitor_inference"],
"indices": [
{
"names": ["customer-*"],
"privileges": ["read", "view_index_metadata"]
}
],
"applications": [
{
"application": "kibana-.kibana",
"privileges": [
"feature_agentBuilder.read",
"feature_actions.read",
"feature_workflowsManagement.read"
],
"resources": ["space:default"]
}
]
}
}
}'
monitor_inferenceis required when agents or tools call the Elasticsearch Inference API. Remove it if they do not.- Replace
customer-*with the index patterns that the client needs. The assigned index privileges allow reads and access to index mappings, but not writes. - Use
kibana-.kibanaas the application name for Kibana feature privileges. feature_agentBuilder.readprovides read-only access to Elastic Agent Builder. The other two privileges provide read-only access to connectors and workflows.- Replace
space:defaultif the client uses a different Kibana space.
- Open the API keys management page and select Create API key.
- Enter a name and expiration for the key.
- Enable Control security privileges.
- Paste the following role descriptor into the editor, then create the key:
{
"agent-builder-read-only": {
"cluster": ["monitor_inference"],
"indices": [
{
"names": ["customer-*"],
"privileges": ["read", "view_index_metadata"]
}
],
"applications": [
{
"application": "kibana-.kibana",
"privileges": [
"feature_agentBuilder.read",
"feature_actions.read",
"feature_workflowsManagement.read"
],
"resources": ["space:default"]
}
]
}
}
monitor_inferenceis required when agents or tools call the Elasticsearch Inference API. Remove it if they do not.- Replace
customer-*with the index patterns that the client needs. The assigned index privileges allow reads and access to index mappings, but not writes. - Use
kibana-.kibanaas the application name for Kibana feature privileges. feature_agentBuilder.readprovides read-only access to Elastic Agent Builder. The other two privileges provide read-only access to connectors and workflows.- Replace
space:defaultif the client uses a different Kibana space.
Remove privileges that the client does not need:
- Remove
feature_actions.readif agents do not use Kibana connectors. - Remove
feature_workflowsManagement.readif agents do not interact with workflows. - Remove
monitor_inferenceif agents and tools do not call the Elasticsearch Inference API.
The following example allows a client to manage Elastic Agent Builder components and workflows while keeping the underlying index access read-only.
POST /_security/api_key
{
"name": "agent-builder-management",
"expiration": "30d",
"role_descriptors": {
"agent-builder-management": {
"cluster": ["monitor_inference"],
"indices": [
{
"names": ["customer-*"],
"privileges": ["read", "view_index_metadata"]
}
],
"applications": [
{
"application": "kibana-.kibana",
"privileges": [
"feature_agentBuilder.all",
"feature_actions.read",
"feature_workflowsManagement.all"
],
"resources": ["space:default"]
}
]
}
}
}
monitor_inferenceis required when agents or tools call the Elasticsearch Inference API. Remove it if they do not.- Replace
customer-*with the index patterns that the client needs. The assigned index privileges allow reads and access to index mappings, but not writes. - Use
kibana-.kibanaas the application name for Kibana feature privileges. feature_agentBuilder.allallows the client to manage Elastic Agent Builder components.feature_actions.readallows it to use connectors, andfeature_workflowsManagement.allallows it to manage workflows.- Replace
space:defaultif the client uses a different Kibana space.
curl --user "${ELASTIC_USERNAME}" \
-X POST "${ELASTICSEARCH_URL}/_security/api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "agent-builder-management",
"expiration": "30d",
"role_descriptors": {
"agent-builder-management": {
"cluster": ["monitor_inference"],
"indices": [
{
"names": ["customer-*"],
"privileges": ["read", "view_index_metadata"]
}
],
"applications": [
{
"application": "kibana-.kibana",
"privileges": [
"feature_agentBuilder.all",
"feature_actions.read",
"feature_workflowsManagement.all"
],
"resources": ["space:default"]
}
]
}
}
}'
monitor_inferenceis required when agents or tools call the Elasticsearch Inference API. Remove it if they do not.- Replace
customer-*with the index patterns that the client needs. The assigned index privileges allow reads and access to index mappings, but not writes. - Use
kibana-.kibanaas the application name for Kibana feature privileges. feature_agentBuilder.allallows the client to manage Elastic Agent Builder components.feature_actions.readallows it to use connectors, andfeature_workflowsManagement.allallows it to manage workflows.- Replace
space:defaultif the client uses a different Kibana space.
Enable Control security privileges and paste the following role descriptor into the editor:
{
"agent-builder-management": {
"cluster": ["monitor_inference"],
"indices": [
{
"names": ["customer-*"],
"privileges": ["read", "view_index_metadata"]
}
],
"applications": [
{
"application": "kibana-.kibana",
"privileges": [
"feature_agentBuilder.all",
"feature_actions.read",
"feature_workflowsManagement.all"
],
"resources": ["space:default"]
}
]
}
}
monitor_inferenceis required when agents or tools call the Elasticsearch Inference API. Remove it if they do not.- Replace
customer-*with the index patterns that the client needs. The assigned index privileges allow reads and access to index mappings, but not writes. - Use
kibana-.kibanaas the application name for Kibana feature privileges. feature_agentBuilder.allallows the client to manage Elastic Agent Builder components.feature_actions.readallows it to use connectors, andfeature_workflowsManagement.allallows it to manage workflows.- Replace
space:defaultif the client uses a different Kibana space.
The feature_agentBuilder.all application privilege does not grant write access to indices. Tools continue to run with only the read and view_index_metadata index privileges assigned to the key.
An unrestricted key can access everything its owner can access. Use this approach only for development or trusted administrative automation. Before using a key in production, replace it with a restricted key that grants only the required spaces, indices, and features.
For short-lived development or administrative automation, you can create a key without role descriptors:
POST /_security/api_key
{
"name": "agent-builder-development",
"expiration": "1d"
}
curl --user "${ELASTIC_USERNAME}" \
-X POST "${ELASTICSEARCH_URL}/_security/api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "agent-builder-development",
"expiration": "1d"
}'
Enter a name and expiration for the key, leave Control security privileges disabled, and create the key.
The key inherits a point-in-time snapshot of the privileges of the user who creates it. It is an administrator key only when the owner has administrator privileges.
The create API returns an encoded value. Store that value securely and send it in the Authorization header:
export API_KEY="<encoded-api-key>"
curl -X GET "${KIBANA_URL}/api/agent_builder/tools" \
-H "Authorization: ApiKey ${API_KEY}"
- Use the
encodedvalue returned by the create API, not the separateidorapi_keyvalues.
For a non-default space, include the space in the request URL and make sure it matches the application privilege resource:
curl -X GET "${KIBANA_URL}/s/production/api/agent_builder/tools" \
-H "Authorization: ApiKey ${API_KEY}"
- The space identifier in the URL must match the role descriptor resource. In this example, the role descriptor must use
"resources": ["space:production"].
The following list pairs common API key symptoms with checks or changes that can resolve them.
401 Unauthorized- Make sure the header uses the
encodedvalue returned by the create API, not the separateidorapi_keyfields. 403 Forbidden- Check that the key has the required Kibana application privilege and that the space in the URL matches the
resourcesvalue. Also make sure the key owner had the privilege when the key was created. - An agent or tool cannot find data
- Check the index patterns and make sure the key has both
readandview_index_metadatafor the required indices. - Connector or model requests fail
- Add
feature_actions.readfor Kibana connectors. Addmonitor_inferencefor Elasticsearch inference endpoints and tools that use the Elasticsearch Inference API. - Workflow requests fail
- Add
feature_workflowsManagement.readto read workflows,feature_workflowsManagement.workflow_executeto run them, orfeature_workflowsManagement.allto manage them. - The create API rejects the role descriptor for a derived key
- Authenticate the create request as a user. When the request is authenticated with an API key, Elasticsearch requires an explicit role descriptor with no privileges.
Learn more about Elasticsearch API keys and Elastic Agent Builder permissions.