Guidance for humans and automated coding agents working in this repository.
Elastic Agent is a unified daemon that collects data from the OS, cloud, containers, and integrations. It runs in standalone mode (local YAML policy) or managed mode (policy from Fleet Server), supervises components as child processes, and ships telemetry to configured outputs (for example Elasticsearch). For a deeper walkthrough, see docs/architecture.md.
Use mage as the primary build and task runner. Install it with:
go install github.com/magefile/mage@latestDiscover targets and flags:
mage -l # List targets
mage -h <Target> # Help for a target (when doc strings are present)Run tasks as mage <namespace>:<target> or mage <target> when documented (for example mage notice). Docstrings in magefile.go describe targets and environment variables.
A Makefile still exists and CI runs targets such as make check-ci and make lint. Prefer mage for local development, but run CI-oriented Makefile targets before opening a PR when practical.
mage build:binary # Main agent binary
mage build:all # All binaries for current platform
mage dev:build # DEV build (debug symbols)
mage test:unit # All unit tests
mage fmt # Format .go and .py files
mage check:all # License headers, integration-test define checks, docs file validation
mage check:lint # golangci-lint on changed files (see make lint)
mage check:lintAll # golangci-lint on entire codebase (see make lint-all)
mage update # Regenerate control protocol, configs, specs
mage tidy # go mod tidy recursively across repo modules
mage clean # Clean build artifactsIntegration tests and packaging often need Docker and extra env vars; see magefile.go and docs/test-framework-dev-guide.md.
- Go version in .go-version
- Docker (packaging and integration tests)
- Git submodules:
git submodule update --init - One-time environment setup:
mage prepare:env
High-level areas:
| Path | Purpose |
|---|---|
internal/pkg/agent/application/ |
Core agent logic: coordinator, config managers, upgrade, monitoring |
internal/pkg/agent/cmd/ |
CLI commands (run, install, enroll, upgrade, status) |
internal/pkg/agent/transpiler/ |
Policy AST and variable substitution |
internal/pkg/composable/ |
Dynamic variable providers |
internal/pkg/agent/fleetapi/ |
Fleet Server HTTP client and action handling |
pkg/component/ |
Component model, spec loading, platform detection |
pkg/component/runtime/ |
CommandRuntime (subprocess) and ServiceRuntime (OS service) |
pkg/control/v2/ |
gRPC control protocol definitions (generated sources under cproto/) |
specs/ |
Component .spec.yml files defining supported inputs/outputs |
deploy/helm/ |
Helm charts (for example elastic-agent and EDOT collector stacks) |
dev-tools/ |
Developer tooling for build, packaging, notice generation, mage targets |
testing/ |
Testing utiliteis including integration test definitions |
docs/ |
Architecture and developer guides |
changelog/ |
Changelog fragments for releases |
build/ |
Produced build and testing artifacts |
Entry flow: main.go → cmd.NewCommand() → Cobra command tree → application.New() initializes platform specs, config managers, and the coordinator.
The beats/ directory is a git submodule (see .gitmodules: elastic/beats). The main module replaces github.com/elastic/beats/v7 with ./beats in go.mod.
Do not edit files under beats/ when implementing changes to the Elastic Agent codebase. Agent work belongs in this repo’s own packages (for example internal/, pkg/, specs/). Submodule bumps are a separate, intentional maintenance step — not part of routine feature or bugfix work.
Refer to architecture.md.
Build artifacts (for example tar, deb, rpm, Docker images) are produced via mage packaging targets; see the test framework guide for environment variables such as AGENT_CORE_SOURCE, EXTERNAL (defaults to true), SNAPSHOT, PLATFORMS, PACKAGES, DEV, DOCKER_VARIANTS. PACKAGES is optional and defaults to tar.gz on non-Windows and zip on Windows; use PACKAGES=all to build all package types. Kubernetes-oriented deployment material lives under deploy/helm/.
Produced artifacts will be placed in the build directory.
mage test:unit # All unit tests (typical pre-PR gate)
mage test:coverage # Unit tests with coverage report
go test -run TestName ./path/to/pkg -v # Single test / packageTreat mage test:unit passing as the minimum bar before considering a change complete. If you add or change integration/E2E behavior, run the relevant mage integration targets and consult the testing docs.
Testing artifacts, including outputs and results will be placed in the build/ directory.
See docs/test-framework-dev-guide.md.
Major direct dependencies agents often interact with (see go.mod for the full graph):
github.com/elastic/beats/v7— Beat libraries (vendored viabeats/submodule; do not edit submodule for agent-only changes)github.com/elastic/elastic-agent-client/v7— agent ↔ component gRPC client protocolgithub.qkg1.top/elastic/go-elasticsearch/v8— Elasticsearch clientgithub.qkg1.top/spf13/cobra— CLIgithub.qkg1.top/rs/zerolog— structured logginggo.elastic.co/apm/v2— APM tracing- OpenTelemetry Collector Contrib packages — EDOT / collector-related integration
google.golang.org/grpc— gRPC (control plane and related RPCs)
The repo contains multiple Go modules; use mage tidy to keep go.mod files consistent when dependencies change.
mage fmt # formats source code (.go and .py) and adds license headers.
mage format:all # format automatically all the codes.
mage format:license # applies the right license header.CI and local checks enforce the following (details in .golangci.yml, magefile.go, and the Makefile):
- Imports / format:
goimportswith local prefixgithub.qkg1.top/elastic(golangci formatters). Usemage fmtfor formatting;mage check:alldoes not run the Go linter (see below). - License headers:
go-licenserwith Elastic License 2.0 (mage check:license/ part ofmage check:all). Thebeatstree is excluded because it is a submodule. - Lint: golangci-lint per .golangci.yml. Notable rules include:
forbidigo:fmt.Print*is forbidden in most code — use structured logging (for example zerolog).depguard: avoid legacymath/rand; prefermath/rand/v2.gomodguard: blocked modules (for example deprecated error/uuid libraries) with suggested replacements.nolintlint://nolintmust include an explanation.gomoddirectives:replacedirectives are restricted to an allow list (see config).
- Lint scope:
mage check:lint/make lint— changed files;mage check:lintAll/make lint-all— entire codebase. Each runs golangci-lint across multiple build-tag sets so files behind//go:buildtags (integration, requirefips, mage, …) are linted too (seebuildTagSetsin dev-tools/mage/lint.go).mage check:allis separate: license headers, integration-testdefine.Requirevalidation, and docs path validation (see magefile.goCheck.All). - Heavy local / CI-style checks:
mage check(from dev-tools/mage/target/common/check.go) runs formatting, registered codegen/update deps (seeinit()in magefile.go),mage tidy, thengo vetand a clean working tree check.make check-cirunsmage check, regeneratesNOTICE, Helm/Kubernetes generation targets, andcheck-no-changes.make checkischeck-ciplusmake lint(golangci-lint). - Generated / spec artifacts: After changing protos, specs, or generated configs, run
mage update(and related targets as described in magefile doc strings). Do not hand-edit generated outputs without regenerating from source. - Docs structure:
mage check:allincludes validation that files expected by docs generation exist (Check.DocsFilesin magefile). - Go toolchain: Version pinned in .go-version.
- FIPS: The codebase supports FIPS-oriented builds and tests (for example
mage test:fIPSOnlyUnit,requirefipsbuild tag). Crypto-related changes should remain compatible with FIPS expectations where applicable.
Principles and repo-specific process: CONTRIBUTING.md.
- Fix the root cause, not a short-term workaround, when possible.
- Keep changes focused; avoid unrelated refactors or scope creep.
- Update docs and tests when behavior, configuration, or operator-facing workflow changes.
- Make non-obvious intent clear through naming, structure, or brief “why” comments when needed.
- Formatting: All go files must be formatted with
go fmtand thegoimportstool, themage fmttarget can be used for this. - Do not modify
beats/for routine Elastic Agent work (submodule boundary). - Changelog: For notable changes, add a fragment using elastic-agent-changelog-tool. Typical usage:
elastic-agent-changelog-tool new "$TITLE"(see the tool’s usage docs). PRs may use theskip-changeloglabel when appropriate; seechangelog/for examples. go.mod/ NOTICE: If you changego.modor add/update Go dependencies, regenerateNOTICE.txtandNOTICE-fips.txtwithmage notice- Before opening a PR (minimum):
mage test:unitand linting (mage check:lintormake lint) should pass. Also runmage check:allwhen your change should satisfy license + integration metadata + docs layout checks. For CI parity, usemake check-ci(see Makefile; notecheck-cidoes not run golangci-lint, which CI runs in GitHub Actions) andmake checkwhen you want the linter plus the samecheck-cisteps. Commit the updated files. This is part ofmake check-ci. Usemage tidyso all modules in the repo stay in sync. - Integration / E2E: When changes affect multi-component or Elasticsearch-backed behavior, run the relevant integration or E2E targets described in the magefile and docs/test-framework-dev-guide.md.
Always use the pull request template when creating a pull request. Always assign the author to the pull request.
Unless instructed otherwise, always add the Team:Elastic-Agent-Control-Plane label to the pull request.
Unless instructed otherwise, always add the backport-active-all label to the pull request when fixing a bug.
- README.md — setup, packaging, dependency hygiene
- docs/architecture.md — architecture overview
- docs/component-specs.md — component spec format
- docs/test-framework-dev-guide.md — integration tests
- Elastic Agent docs — product documentation
- Fleet Server - Control protocol server for managed agents