Configure Unified Service Tags and verify Single Step Instrumentation (SSI) injection on Linux hosts — SSI automatically instruments applications for APM without code changes. Only use if the Datadog Agent is already installed.
npx skills add https://github.com/datadog-labs/agent-skills --skill enable-ssi
> Before doing anything else: Fully resolve all variables in ## Context to resolve before acting. Do not begin Step 0 until every variable has a concrete value.
Invoke this skill when:
DD_APM_INSTRUMENTATION_ENABLED=host was used) and you need to configure Unified Service Tags on the application serviceDD_SERVICE, DD_ENV, DD_VERSION on a running service/proc/<pid>/maps doesn't show the language tracer (launcher-only injection)Do NOT invoke this skill if:
agent-install first/opt/datadog-packages/ — re-run agent-installdd-apm-k8s-enable-ssi insteadWhen the install script runs with DD_APM_INSTRUMENTATION_ENABLED=host, it:
datadog-apm-inject and language library packages under /opt/datadog-packages//etc/ld.so.preloadWhat SSI does NOT configure automatically:
DD_SERVICE, DD_ENV, DD_VERSION — these must be set on the application process for traces to be tagged correctlyDD_SERVICE, the tracer auto-detects a service name (often the process name or framework name), which may not match what the user expectsVerify SSI is armed:
ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST> \
"cat /etc/ld.so.preload && ls /opt/datadog-packages/ | grep apm"
If /etc/ld.so.preload contains a path to the launcher, and /opt/datadog-packages/datadog-apm-inject exists — SSI is armed.
ERROR: Either missing — run agent-install first.
Check for existing manual instrumentation:
ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST> "
grep -r 'import ddtrace\|from ddtrace\|require .dd-trace.\|opentelemetry' <SOURCE_DIR> 2>/dev/null | head -5 || echo 'No manual instrumentation found'
"
ERROR: Manual instrumentation found — SSI silently disables itself when it detects an existing tracer. Remove the manual import/package before proceeding.
Check base libc:
ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST> \
"ldd --version 2>&1 | head -1"
ERROR: musl — SSI requires glibc. No workaround; must use a glibc-based OS.
| Variable | How to resolve |
|---|---|
| SERVICE_NAME | Ask the user — how the service should appear in Datadog APM (e.g. payment-api) |
| ENV | Ask the user — environment name (e.g. production, staging, dev) |
| VERSION | Ask the user or read from the app's version file / git tag |
| SYSTEMD_SERVICE_NAME | From systemctl list-units --type=service --state=running on the host — the unit running the app |
| SSH_KEY | Path to SSH private key |
| SSH_USER | SSH username |
| SSH_HOST | Hostname or IP of the target host |
pip uninstall ddtrace, remove import ddtrace / ddtrace-run from CMDnpm uninstall dd-trace, remove require('dd-trace')-javaagent:/path/to/dd-java-agent.jar JVM flaggem uninstall ddtrace, remove require 'ddtrace'Datadog.Trace NuGet and profiler env varsAfter removing, restart the service. Confirm with the user before restarting. Tell the user: "I need to restart <SYSTEMD_SERVICE_NAME> to remove the old instrumentation. This will cause a brief outage. Ready to proceed?" Wait for confirmation.
Without UST, traces arrive with an auto-detected service name that may not match user expectations, and won't be tagged with env or version.
For systemd-managed services (most common):
ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST> \
"sudo systemctl cat <SYSTEMD_SERVICE_NAME>"
Add a drop-in override (preserves the original unit file):
ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST>
sudo systemctl edit <SYSTEMD_SERVICE_NAME>
Add to the editor:
[Service]
Environment="DD_SERVICE=<SERVICE_NAME>"
Environment="DD_ENV=<ENV>"
Environment="DD_VERSION=<VERSION>"
Apply:
ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST> \
"sudo systemctl daemon-reload && sudo systemctl show <SYSTEMD_SERVICE_NAME> | grep -E 'DD_SERVICE|DD_ENV|DD_VERSION'"
If the UST vars appear in the output — configuration applied.
For supervisord:
# In [program:<name>] section of supervisord.conf
environment=DD_SERVICE="<SERVICE_NAME>",DD_ENV="<ENV>",DD_VERSION="<VERSION>"
Reload: sudo supervisorctl reload
For pm2:
// ecosystem.config.js
env: { DD_SERVICE: "<SERVICE_NAME>", DD_ENV: "<ENV>", DD_VERSION: "<VERSION>" }
Reload: pm2 reload <app>
Confirm with the user before restarting. Tell the user: "I need to restart <SYSTEMD_SERVICE_NAME> for SSI to inject into it. This will cause a brief outage. Ready to proceed?" Wait for confirmation.
ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST> \
"sudo systemctl restart <SYSTEMD_SERVICE_NAME> && sleep 3 && sudo systemctl is-active <SYSTEMD_SERVICE_NAME>"
If active is returned — service is running.
ERROR: Returns failed — check logs:
ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST> \
"sudo journalctl -u <SYSTEMD_SERVICE_NAME> --since '1 minute ago' | tail -30"
ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST> \
"pgrep -a -f '<SERVICE_NAME>' | head -3"
Use the PID:
# Authoritative injection check
ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST> \
"sudo cat /proc/<PID>/maps | grep -E 'launcher|apm-library|datadog'"
# UST vars in process environment
ssh -o StrictHostKeyChecking=no -i <SSH_KEY> <SSH_USER>@<SSH_HOST> \
"sudo cat /proc/<PID>/environ | tr '\0' '\n' | grep -E 'DD_SERVICE|DD_ENV|DD_VERSION'"
If both the launcher and language library appear in maps, and UST vars are in environ — SSI and tagging are fully configured.
ERROR: Launcher in maps but no language library — injection attempted but failed. Run:
pup apm troubleshooting list --hostname <DD_HOSTNAME> --timeframe 15m
Go to troubleshoot-ssi if errors are present.
Exit when ALL of the following are true:
/proc/<PID>/mapsDD_SERVICE, DD_ENV, DD_VERSION present in /proc/<PID>/environAutomatically proceed to verify-ssi now — do not ask the user for permission.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.
Build agentic applications with GitHub Copilot SDK. Use when embedding AI agents in apps, creating custom tools, implementing streaming responses, managing sessions, connecting to MCP servers, or creating custom agents. Triggers on Copilot SDK, GitHub SDK, agentic app, embed Copilot, programmable agent, MCP server, custom agent.
Coding Agent Session Search - unified CLI/TUI to index and search local coding agent history from Claude Code, Codex, Gemini, Cursor, Aider, ChatGPT, Pi-Agent, Factory, and more. Purpose-built for AI agent consumption with robot mode.
Destructive Command Guard - High-performance Rust hook for Claude Code that blocks dangerous commands before execution. SIMD-accelerated, modular pack system, whitelist-first architecture. Essential safety layer for agent workflows.
Makepad UI development skills for Rust apps: setup, patterns, shaders, packaging, and troubleshooting.
Secure environment variable management ensuring secrets are never exposed in Claude sessions, terminals, logs, or git commits
Prompt for generating an AGENTS.md file for a repository
Take datadog-labs/agent-enable-ssi from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.