GitHub Copilot CLI session tracing

Send GitHub Copilot CLI agent sessions to Future AGI with Copilot's built-in OpenTelemetry export. Prompts and tool arguments stay off by default.

About

GitHub Copilot can export every agent interaction as an OpenTelemetry trace: one invoke_agent span for the user message, one chat span per model call, and one execute_tool span per tool call. Point that export at Future AGI and each Copilot agent turn shows up as a trace in Observe, with model names, token counts, tool names, and timings. Prompts, responses, and tool arguments are not exported unless you turn content capture on.

This guide covers Copilot CLI 1.0.98 only, using its native OTLP/HTTP exporter. VS Code Copilot Chat is a separate surface and has no Future AGI setup instructions on this page.

See GitHub’s CLI OpenTelemetry reference for the exporter settings.

What you get

One Copilot agent turn becomes one trace. A Copilot CLI turn that lists a folder and reads a file looks like this in Future AGI:

invoke_agent                       conversation id, total tokens, turn count
├── chat gpt-6-luna                model, input/output/cached tokens, finish reason
├── execute_tool glob              tool name, tool call id
├── execute_tool bash bash         tool name, tool call id, exit code
├── chat gpt-6-luna
├── execute_tool view
└── chat gpt-6-luna
SpanKey attributes (content capture off)
invoke_agentgen_ai.conversation.id, gen_ai.usage.input_tokens, gen_ai.usage.output_tokens, github.copilot.turn_count, github.copilot.agent.type, error.type on failure
chat <model>gen_ai.request.model, gen_ai.response.model, gen_ai.usage.* tokens (including cache read/write), gen_ai.response.finish_reasons, gen_ai.response.time_to_first_chunk
execute_tool <tool>gen_ai.tool.name, gen_ai.tool.call.id, gen_ai.tool.type, process.exit.code for shell tools, error.type on failure
Span status / hook errorsRaw failure text may be present even with content capture off: status messages, exception events, or CLI github.copilot.hook.error_message

Prerequisites

  • A Future AGI account and your API key and secret key (Settings > API Keys).
  • GitHub Copilot access on your GitHub account. Use an account entitled to Copilot CLI.
  • Install the CLI version used by this guide: npm install -g @github/copilot@1.0.98, then copilot login once.

Set up the Copilot CLI

Set the exporter variables

Set the exporter variables on the Copilot process only, with a copilot shell function (add it to ~/.zshrc or ~/.bashrc; it holds no keys):

copilot() {
  OTEL_EXPORTER_OTLP_ENDPOINT="https://api.futureagi.com/tracer" \
  OTEL_EXPORTER_OTLP_HEADERS="X-Api-Key=${FI_API_KEY},X-Secret-Key=${FI_SECRET_KEY}" \
  OTEL_RESOURCE_ATTRIBUTES="project_name=my-copilot-sessions,project_type=observe" \
  command copilot --secret-env-vars=FI_API_KEY,FI_SECRET_KEY,OTEL_EXPORTER_OTLP_HEADERS "$@"
}

Setting OTEL_EXPORTER_OTLP_ENDPOINT turns Copilot’s exporter on. Copilot appends /v1/traces, so the base URL ends at /tracer. project_name is required: Future AGI creates the project on the first export and rejects spans without it.

--secret-env-vars removes the named variables from the shell commands and MCP servers Copilot starts, and redacts their values from Copilot’s output. Copilot’s own exporter still uses them. Copilot CLI 1.0.98 already keeps OTEL_* variables out of its shell commands; the flag is what keeps FI_API_KEY and FI_SECRET_KEY out.

The function reads FI_API_KEY and FI_SECRET_KEY from the shell you run it in, so set them only for that terminal session (for example from your password manager’s CLI), not in a shell profile. The trade-off: other programs you start from that terminal can still read the two keys, but only Copilot gets the exporter settings.

Avoid the simpler export OTEL_EXPORTER_OTLP_* in your shell. Then every program started from that shell, including other OpenTelemetry-instrumented tools, sends its telemetry to Future AGI with your keys.

Run an agent session

Start an interactive session in a folder whose contents you are comfortable sharing with your model provider:

cd ~/code/my-project
copilot

Ask: List the files in this folder and read README.md, then summarize it in one sentence. Review each tool permission before approving it. Each message you send becomes its own invoke_agent trace.

Note

With -p, Copilot exits after the answer and waits about one second for the exporter, so the first trace can be lost. Create the project in Future AGI before the first -p run, or start with an interactive session.

Find the trace

Open Observe in Future AGI and select the my-copilot-sessions project. The newest trace has an invoke_agent root with chat and execute_tool children. Filter on gen_ai.conversation.id to see every turn from one Copilot session.

The repository example examples/coding-agents/github-copilot includes the same function in copilot-otel.sh.

Privacy

By default Copilot exports mostly metadata: model names, token counts, durations, tool names, and IDs. Prompt and tool message bodies are off by default. However, some vendor fields remain free text even when content capture is off, including hook command paths and raw failure text.

Other fields you should know about:

FieldWhen it is sentNotes
enduser.pseudo.id (CLI)When availablePseudonymous Copilot user ID, not an email or login
github.copilot.git.repository, .branch, .commit_sha (CLI)When the workspace is a Git repositoryRepository remote URL, current branch and commit
github.copilot.context.skills, .custom_agent_names, .mcp_server_names (CLI)When the session uses themSkill names, custom agent names and hashed MCP server names
github.copilot.skill.invoked event and execute_tool skill <name> span (CLI)When the agent runs a skillWith content capture off: the skill name (gen_ai.skill.name), what triggered it (github.copilot.skill.invocation_trigger), and where it was loaded from (github.copilot.skill.source, for example project). The skill file’s location (gen_ai.skill.source.uri, a local file:// path), description, and body (github.copilot.skill.content) are added only when content capture is on.
Status messages and github.copilot.hook.error_messageOn failuresRaw failure text can contain paths or hook/tool output

Note

Teams with strict data rules can remove the hook command, status messages, and hook error text before they reach Future AGI. Point Copilot’s exporter at your own OpenTelemetry Collector (otelcol-contrib 0.162.0) and add this transform processor to its traces pipeline. Spans keep their error status; only the text is removed.

processors:
  transform/copilot-redact:
    error_mode: ignore
    trace_statements:
      - context: span
        statements:
          - delete_key(attributes, "copilot_chat.hook_command")
          - set(status.message, "") where status.message != ""
      - context: spanevent
        statements:
          - delete_key(attributes, "github.copilot.hook.error_message")
          - delete_key(attributes, "exception.message")
          - delete_key(attributes, "exception.stacktrace")

Have the collector forward to https://api.futureagi.com/tracer/v1/traces with the X-Api-Key and X-Secret-Key headers. Future AGI accepts gzip-encoded and uncompressed OTLP, so the exporter’s default compression works.

To capture prompt and tool content for one CLI session, run OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true copilot through the wrapper. Opt in only in a trusted environment.

With content on, spans add gen_ai.input.messages, gen_ai.output.messages, gen_ai.system_instructions, gen_ai.tool.definitions, gen_ai.tool.call.arguments, and gen_ai.tool.call.result. In Future AGI they appear in the span’s Attributes, not in the trace list’s Input and Output columns. They can contain source code, file contents, secrets that appear in your files, and local paths such as your working directory and skill file locations.

What is not available

  • Inline completions (ghost text), next edit suggestions, and Copilot code review do not produce these traces.
  • The Copilot cloud agent that works on GitHub and opens pull requests is not covered. Its sessions run on GitHub, not on your machine.
  • Session grouping. Future AGI’s Sessions view groups traces by the session.id span attribute. If spans contain gen_ai.conversation.id but not session.id, each user message is a separate trace and Sessions stays empty. Filter on gen_ai.conversation.id to follow one conversation.
  • Cost in currency. github.copilot.cost is a billing multiplier and github.copilot.nano_aiu counts AI units. Neither is a dollar amount, and Future AGI does not convert them.
  • Metrics and events. Copilot also exports OTel metrics. The Future AGI collector accepts traces only, so metric exports are rejected with HTTP 404 (Copilot logs HTTP export failed with status code: 404 at exit). Traces are not affected.
  • Span type for invoke_agent. Future AGI classifies chat spans as LLM and execute_tool spans as tools; the invoke_agent root shows type unknown.
  • Standalone custom_notification traces. Copilot CLI can export a one-span custom_notification trace for shell completion, idle, or permission notifications. Future AGI shows it as type unknown; it is safe to ignore or filter.
  • The local file and SQLite exporters (COPILOT_OTEL_FILE_EXPORTER_PATH) are debugging aids, not the setup path.

This page is about Copilot as an application. It is not a wrapper for GitHub Models or for model calls your own code makes; use a traceAI integration for those.

Troubleshooting

SymptomFix
Spans rejected with 401 or 403OTEL_EXPORTER_OTLP_HEADERS must be X-Api-Key=...,X-Secret-Key=... with no spaces or quotes inside the value.
Spans rejected with a project_name errorAdd project_name=... to OTEL_RESOURCE_ATTRIBUTES.
404 from the collectorIf no traces arrive and the 404 is for traces (not meter shutdown), the endpoint is a base URL. Use https://api.futureagi.com/tracer, not .../tracer/v1/traces. A meter-shutdown 404 is expected because Future AGI accepts traces only.
Prompts are visible in spansContent capture is on. Unset OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT or COPILOT_OTEL_CAPTURE_CONTENT before running the CLI.

Next steps

Was this page helpful?

Questions & Discussion