Working with an agent
The loop an agent runs through the MCP server to change, test, publish, and deploy a collector configuration.
An agent connected to the MCP server changes a configuration in the same steps you would take with the CLI, one tool call per step, and the server describes these steps in the instructions it gives clients. This page walks through the loop so you can steer the agent and read what it reports.
The edit loop
- Find.
list_configurationsreturns the configurations you can see (your own and every published one) withid, published state, latestversion_number, and collector pin. - Read.
get_configuration_versionreturns the latest version's YAML and its collector pin. - Validate. The agent edits the YAML in its own context and checks it with
validate_configuration, passingconfiguration_idso the check runs on the pinned collector. After editing atransform,filter,routing, ortail_samplingblock, it also runslint_ottl. - Push.
push_configurationsaves the YAML as a version and returns itsversion_number. - Test.
run_pipeline_testreplays a sample through one pipeline of the stored version and checks the agent's assertions. - Publish.
publish_configuration_version, orpublish: trueon the push. - Deploy.
deploy_configurationassigns the published version to a fleet's deploy group.
Three results send the agent back to step 3 with findings to fix: valid: false from validation or lint, status: "invalid" from a push, and a test that ends Fail, or Error when stderr shows the collector rejected the configuration. A result with isError set means the call itself failed, for example on a 401, the rate limit, or an unavailable validator; see Results and errors.
Which collector runs it
Every configuration version is pinned to a collector distribution and version, and a result holds only for the collector it ran on. Validation and pipeline tests use the first match in this order.
collector_versionanddistributionpassed on the call.- The stored configuration's pin. It applies automatically when the call targets the stored configuration:
push_configuration, andrun_pipeline_testwithconfiguration_idand noyaml. For YAML the agent holds, it applies only when the call also passesconfiguration_id, and comes from the latest version, or fromversionwhen a test passes one. - The server default: OpenTelemetry Collector Contrib at the default collector version.
The two inputs fall through separately, so a call that passes only collector_version still takes the distribution from the pin. YAML validated on the server default can pass there and still fail on push or in the fleet.
The API offers only otelcol-contrib as a distribution you can name. Validating or testing YAML with the configuration_id of a configuration locked to another distribution in the app, such as ClickStack, is refused with Unknown collector distribution, as is a push once its latest version is published; a test of its stored version still runs on its pin. The push returns status: "invalid", which no YAML edit clears; a push onto a draft checks the YAML on OpenTelemetry Collector Contrib at the pinned version.
Push and publish
| Latest version | What push_configuration does | action |
|---|---|---|
| A draft | Edits it in place; the server validates the YAML. | patched |
| Published | Validates the YAML on that version's pin, then appends a new version labeled with description. | appended |
A push returns status: "saved", or status: "invalid" with the validator's errors. The agent reads version_number from the result, since a push onto a draft keeps the draft's number. Published versions are immutable, and publishing one again succeeds. A configuration that was never published is visible only to its author, so one the agent creates with a service-account token appears to you and your teammates only once a version is published. See Versions & publishing.
Pipeline tests
run_pipeline_test runs the same pipeline tests as the editor's Testing tab and telflo test: a real collector in a sandbox replays sample_text through one pipeline and evaluates the rules, OTTL assertions over what the pipeline emits. The sandbox strips connectors, removes every pipeline but the target, and does not substitute organization variables, so inline real values.
The sample must match the pipeline's receiver: OTLP JSON for OTLP receivers, raw lines for filelog, and syslog lines for syslog. The call tests a stored version with configuration_id (the latest, or version), or YAML the agent holds with yaml. The whole request must fit the size limit.
Write the rules
Each rule is one OTTL assertion. This example tests a transform processor that replaces user.email with its SHA-256 hash, on ten log records: four with an email address and six without, one of them a health check with the body health check ok.
{
"configuration_id": "<configuration id>",
"signal_type": "logs",
"pipeline": "logs/in",
"sample_text": "<OTLP JSON with the ten log records>",
"rules": [
{
"name": "total count",
"context": "log",
"quantifier": "count",
"condition": "true",
"count": { "operator": "eq", "value": 10 }
},
{
"name": "emails hashed",
"context": "log",
"quantifier": "count",
"condition": "IsMatch(attributes[\"user.email\"], \"^[0-9a-f]{64}$\")",
"count": { "operator": "eq", "value": 4 }
},
{
"name": "health check untouched",
"context": "log",
"quantifier": "count",
"condition": "body == \"health check ok\" and attributes[\"user.email\"] == nil",
"count": { "operator": "eq", "value": 1 }
},
{
"name": "no raw email left",
"context": "log",
"quantifier": "none",
"condition": "IsMatch(attributes[\"user.email\"], \"@\")"
}
]
}The first three rules are the controls every test should carry:
- Total count.
condition: "true"with thecountquantifier fixes how many records survive, so a processor that drops records fails the test. - Proof the processor acted.
emails hashedasserts the effect, a 64-character hex value, without naming a value from the sample. - Untouched control. A record the processor must not match survives unchanged. Exact values are fine here and for values the configuration hard-codes.
The fourth rule is a leak check. The CLI's authoring rules on quantifiers, tautologies, and regex escaping apply unchanged, and Tools lists every rule field.
Wait for the result
run_pipeline_test waits up to wait_seconds (0 to 90, default 45) for the run to finish. A longer run returns status: "Running" with its id, last_status, a next hint, and a poll_error if reading the status failed; the agent passes the id as run_id to get_test_run every few seconds until the status is Success, Fail, or Error. The tool's own polling counts against the rate limit.
Read the results
Fail means the collector ran and an assertion failed; each entry in validation_results reports passed and, on failure, an error_message or a failure_detail with samples and counts. Error means the collector or the sandbox failed, and stderr is the place to look first. A Fail, or an Error whose stderr shows the collector rejected the configuration, sends the agent back to the YAML; stderr that starts with The test was never executed: means the sandbox never ran it, so the agent retries later. get_test_run_output returns what the target pipeline emitted, which shows why a rule did not match; a 404 means the run has not finished or produced no output.
Save rules to the Validation sub-tab
The editor's Testing tab has a Validation sub-tab of saved rules, one set per version and pipeline, which a plain run never changes. Two inputs use it. Both need configuration_id without yaml, and every run's result reports rules_source as saved or inline.
save_rules: truesavesrulesforpipeline, then runs the version's saved set. It replaces only rules saved earlier through the API, keeps rules added by hand in the app, and reports both counts undervalidation_pipeline. Use it once the assertions pass.use_saved_rules: trueruns the rules the version already has. Passingrulesas well is refused.
get_validation_rules shows what is saved on a version. A service-account token can save rules onto configurations its service account created or that are published. See Validating output.
Deploy
deploy_configuration assigns a configuration version to a deploy group, which the API and the tools call a deployment (deployment_id, list_deployments). Without version, it deploys the published version and fails when there is none.
| Situation | What happens |
|---|---|
deployment_id is given | That group is updated to this configuration and version. |
| Exactly one group in the fleet serves the configuration | That group is updated, and name is ignored. |
| Several serve it | An error lists them; pass deployment_id. |
| None serves it | With name, a new group is created. Without it, an error asks for name. |
name and role apply only when the tool creates a group. To point another existing group at the configuration, pass its deployment_id; to run the configuration in an additional new group alongside the current one, create the group on the fleet's Deploy Groups tab in the app. A new group on a Kubernetes supervisor fleet needs a role of node, cluster, or gateway, which cannot be changed later, and its namespace defaults to telflo-collectors; on a server fleet, leave role out.
Collectors pick up the version on their next check-in, and deploying an earlier published version rolls back. See Update the configuration.
Install collectors
To install into a new fleet, create it with create_fleet as a server fleet (server-supervisor) or a Kubernetes supervisor fleet (kubernetes-supervisor). get_fleet_install_command returns the same command as the app's install dialogs and telflo fleet install.
platform | Fleet type | Returns |
|---|---|---|
docker | Server fleet | A container run command. |
linux | Server fleet | The All In One supervisor bundle command, through a Quick Deploy URL valid for 24 hours. |
kubernetes | Kubernetes supervisor fleet | A curl for the deploy group's values.yaml, through a URL valid for 24 hours, and the helm command that installs it. |
A server fleet installs into its Default deploy group unless deployment_id names another. A Kubernetes supervisor fleet needs a deploy group first, created with deploy_configuration, and needs deployment_id only when it has several.
env sets the variables the configuration reads (names use letters, digits, and _, and do not start with a digit), and env_var_names lists every name the collector expects. A variable left without a value becomes a <value> placeholder in the Docker and Kubernetes commands; the Linux bundle leaves it for you to set on the host. Where the result's notes say --env NAME=value, pass the value in env. The agent should not run the command unless its own machine is the target host. See Install collectors.
The Docker and Linux commands and the result's token field carry the fleet's install token, and the Kubernetes command downloads a values.yaml that holds it, so hand the command to the operator who runs it and see Secrets in transcripts if it leaks.
Start from a flow
list_flowsreturns the catalog, with the collector each flow was validated on.get_flowreturns one flow's description andyaml.validate_configurationwith that YAML and noconfiguration_idchecks it on the server default, the collector the new configuration will run on.create_configurationwith anameand the YAML creates an unpublished draft, version 1.
create_configuration has no collector pin input, the same gap as telflo config create, so the new configuration runs on OpenTelemetry Collector Contrib at the server's default version, which can differ from the one the flow was validated on. When the flow's version matters, create the configuration with Use this flow in the app, which pins it, and give the agent its name. See Flows.
Example prompts
Each prompt is one line to give the agent, with the tools it typically calls.
| Prompt | Tools |
|---|---|
| Which of our configurations have unpublished drafts, and what collector version is each on? | list_configurations |
In checkout-gateway, hash user.email in the logs/in pipeline, then validate, push, and test it with a count control, proof it hashed, and an untouched record. | list_configurations, get_configuration_version, validate_configuration, lint_ottl, push_configuration, run_pipeline_test |
| That test passed on version 7, so save its rules to the Validation tab. | run_pipeline_test with save_rules |
| Publish version 7 of checkout-gateway and deploy it to the prod-east fleet. | list_configurations, publish_configuration_version, list_fleets, deploy_configuration |
Give me the Linux arm64 install command for the edge-hosts fleet, with OTLP_ENDPOINT set to https://otlp.example.com. | list_fleets, get_fleet_install_command |
| Find a flow for tail sampling and start a configuration from it called payments-sampling. | list_flows, get_flow, validate_configuration, create_configuration |
| The test you just ran ended in Error, so read its stderr and output and tell me what broke. | get_test_run, get_test_run_output |
Last updated on