# How Trace Context Propagation Works Across Firstmate Secondmates

> Discover how Firstmate enables W3C trace context propagation across processes, including nested and remote secondmates, by injecting a single traceparent carrier via the TRACEPARENT environment variable.

- Repository: [Kun Chen/firstmate](https://github.com/kunchenguid/firstmate)
- Tags: deep-dive
- Published: 2026-08-13

---

**Firstmate implements W3C trace-context propagation in a default-off mode, freezing the enablement decision at home-session start and injecting a single traceparent carrier into every spawned process—including nested and remote secondmates—via the TRACEPARENT environment variable.**

Trace context propagation in the Firstmate orchestration system ensures distributed traces remain consistent across complex hierarchies of workers and secondmates. When enabled, the system resolves one `traceparent` carrier per task and propagates it through the entire execution chain, from the primary home session down to remote secondmates, while guaranteeing immutable configuration within each session boundary.

## Enabling Trace Context Propagation in Firstmate

Firstmate treats trace-context propagation as an opt-in feature controlled by presence-based configuration and environment overrides.

### Configuration Flags and Environment Variables

You activate the feature by creating a presence flag at `config/trace-context` within your Firstmate home directory. Alternatively, set the `FM_TRACE_CONTEXT` environment variable to override the configuration file.

```bash

# Enable via presence flag

mkdir -p "$HOME_DIR/config"
touch "$HOME_DIR/config/trace-context"

# Or enable via environment override

export FM_TRACE_CONTEXT=1

```

### The Frozen Session Decision

At the start of every home session, `fm_trace_context_session_start` (defined in [`bin/fm-trace-context-lib.sh`](https://github.com/kunchenguid/firstmate/blob/main/bin/fm-trace-context-lib.sh) lines 59-71) reads the enablement state and writes a frozen decision to `state/.trace-context-effective`. This decision binds to the session lock pid, meaning any subsequent edits to `config/trace-context` or `FM_TRACE_CONTEXT` are ignored until the session releases its lock and restarts.

```bash

# The frozen decision is written once per locked session

bin/fm-trace-context-lib.sh fm_trace_context_session_start "$HOME_DIR/config" "$HOME_DIR/state/.trace-context-effective"

```

## Trace Context Inheritance in Secondmates

Secondmates inherit trace-context configuration through a combination of launch-time prefix injection and the generic inheritable-config mechanism.

### How Secondmates Inherit the Configuration

When spawning a secondmate, [`bin/fm-spawn.sh`](https://github.com/kunchenguid/firstmate/blob/main/bin/fm-spawn.sh) passes the primary home’s frozen decision via the launch prefix. The system also copies the configuration into the secondmate’s environment through `FM_INHERITABLE_CONFIG`, which ensures the `config/trace-context` flag persists into the child environment.

### Independent Session Freezing

Each secondmate runs its own `fm_trace_context_session_start` logic upon initialization. It reads the inherited flag from its own `config/trace-context` and writes a separate frozen decision to its `state/.trace-context-effective` file. This guarantees that nested secondmates independently freeze the same enablement decision without referencing back to the parent after startup.

The inheritance mechanism is validated in [`tests/fm-secondmate-harness.test.sh`](https://github.com/kunchenguid/firstmate/blob/main/tests/fm-secondmate-harness.test.sh) (lines 295-309) and [`tests/fm-secondmate-safety.test.sh`](https://github.com/kunchenguid/firstmate/blob/main/tests/fm-secondmate-safety.test.sh) (lines 309-353).

## Carrier Resolution and Task Injection

When Firstmate spawns any task—including workers and secondmates—it resolves the traceparent carrier through a deterministic resolution chain.

### The fm_trace_context_resolve Function

Located in [`bin/fm-trace-context-lib.sh`](https://github.com/kunchenguid/firstmate/blob/main/bin/fm-trace-context-lib.sh) (lines 18-27), `fm_trace_context_resolve` implements the following logic:

- If trace-context is disabled, the function returns nothing and the spawn proceeds without `TRACEPARENT` export.
- If enabled, it first checks the task’s meta file at `state/<id>.meta` for an existing `traceparent=` entry (recovery path).
- If absent, it calls `fm_trace_context_mint` (lines 5-12) to generate a fresh carrier using cryptographically-random entropy validated against the W3C format.

```bash

# Resolve or mint a carrier for a specific task

TRACEPARENT_VALUE=$(bin/fm-trace-context-lib.sh fm_trace_context_resolve "$HOME_DIR/config" "state/<task-id>.meta")

```

### Task Metadata Persistence

The resolved carrier is injected into the spawned process environment as `TRACEPARENT` and simultaneously recorded in the task’s meta file. This dual recording ensures that task relaunches or crash recoveries reuse the exact same trace identifier, maintaining trace continuity across retries.

## Remote Secondmate Propagation

For remote secondmates, propagation follows a strict command-line delegation pattern rather than environment inheritance. The primary home resolves the carrier using the standard resolution flow, then passes it explicitly via the `--traceparent` flag to [`fm-spawn.sh`](https://github.com/kunchenguid/firstmate/blob/main/fm-spawn.sh).

```bash

# Primary home resolves and transmits

TRACE=$(bin/fm-trace-context-lib.sh fm_trace_context_resolve "$HOME/config" "state/<task>.meta")
bin/fm-spawn.sh --remote secondmate-host --traceparent "$TRACE" ...

```

The remote host’s secondmate receives the carrier through the launch argument, records it in its own `state/<id>.meta`, and does not inherit any further trace-context flags from the parent environment. This isolation ensures remote workers have a single, unambiguous source of trace truth. The complete remote propagation flow is exercised in [`tests/fm-remote-secondmate-trace-context.test.sh`](https://github.com/kunchenguid/firstmate/blob/main/tests/fm-remote-secondmate-trace-context.test.sh) (lines 140-272).

## Session-Bound Immutability Guarantees

Firstmate protects against configuration drift by binding the trace-context decision to the session lifecycle. Because `state/.trace-context-effective` is tied to the specific session lock pid, only a full session restart (lock release and reacquisition) can re-evaluate the enablement flag. This immutability prevents stale or conflicting configurations when deeply nesting secondmates or when configuration files change mid-execution.

Verification of this session-bound behavior appears in [`tests/fm-trace-context-lib.test.sh`](https://github.com/kunchenguid/firstmate/blob/main/tests/fm-trace-context-lib.test.sh) (lines 31-38) and [`tests/fm-session-start.test.sh`](https://github.com/kunchenguid/firstmate/blob/main/tests/fm-session-start.test.sh) (lines 830-856).

## Summary

- **Default-off architecture**: Trace-context propagation requires explicit activation via `config/trace-context` presence flag or `FM_TRACE_CONTEXT` environment variable.
- **Frozen decisions**: Each session computes an immutable enablement decision at startup, stored in `state/.trace-context-effective` and bound to the session lock.
- **Secondmate inheritance**: Child secondmates receive configuration through `FM_INHERITABLE_CONFIG` and independently freeze their own decisions upon session start.
- **Single-carrier-per-task**: The `fm_trace_context_resolve` function guarantees exactly one traceparent value per task, reused across relaunches via metadata storage in `state/<id>.meta`.
- **Remote delegation**: Remote secondmates receive trace context exclusively through the `--traceparent` launch argument, not environment inheritance.

## Frequently Asked Questions

### How do I enable trace context propagation in Firstmate?

Create a presence flag file at `config/trace-context` in your Firstmate home directory, or set the `FM_TRACE_CONTEXT` environment variable. The system detects either condition during `fm_trace_context_session_start` and activates propagation for the duration of that session.

### What happens if I change the config/trace-context file during a session?

Changes are ignored. Firstmate writes a frozen decision to `state/.trace-context-effective` at session start and binds it to the session lock pid. Only after releasing the session lock and starting a new session will the system re-read the configuration flag.

### How does trace context work with remote secondmates?

For remote secondmates, the primary home resolves the traceparent carrier locally and passes it via the `--traceparent` flag to [`fm-spawn.sh`](https://github.com/kunchenguid/firstmate/blob/main/fm-spawn.sh). The remote secondmate records this value in its task meta and uses it directly, without inheriting any trace-context environment variables from the parent host.

### Where is the traceparent value stored for task recovery?

Each task’s traceparent is stored in `state/<task-id>.meta` with the prefix `traceparent=`. When `fm_trace_context_resolve` runs for a task, it checks this file first; if a valid entry exists, it reuses that exact carrier rather than minting a new one, ensuring trace continuity across task restarts or crash recoveries.