agentleFS
coreweavecoreweave/forge-agent-lens-for-claude-code/AGENTS.md

forge-agent-lens-for-claude-code

AGENTS.md9 starsChanged 24 days agoApache-2.0View on GitHub

Notes for agents working on this repo. Everything below was verified against live traces, not inferred. Each of these looks like a bug and is not. Check here before filing one. - **genai.usage.inputtokens sums three fields.** buildUsage in src/genaiSpans.ts adds Anthropic's inputtokens, cachereadinputtokens and cachecreationinput_tokens, because OTel defines input tokens as the total prompt. The cache fields are also emitted separately as the breakdown, which reads like double counting but is not. See the comment and the semconv link at…

  • Reads credentials

We split this AGENTS.md into the rules it gives an agent

1 rule. About 0 are common, 0 are distinctive, and 1 is very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈0

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 1

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Read through Session.parseTranscript(), which treats an unreadable transcript as empty.

    line 74

≈ “Common” is an estimate: at least 1 in 5 of the 36,368 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
AGENTS.md

AGENTS.md

Notes for agents working on this repo. Everything below was verified against live traces, not inferred.

Settled decisions: do not "fix" these

Each of these looks like a bug and is not. Check here before filing one.

  • gen_ai.usage.input_tokens sums three fields. buildUsage in src/genaiSpans.ts adds Anthropic's input_tokens, cache_read_input_tokens and cache_creation_input_tokens, because OTel defines input tokens as the total prompt. The cache fields are also emitted separately as the breakdown, which reads like double counting but is not. See the comment and the semconv link at the function.
  • A turn's last chat span appears only at Stop. Earlier ones are sent at root PreToolUse (Session.emitCompletedResponses). Claude Code writes the rest of a response after running its tool, and a sent span cannot be amended.
  • The first chat span carries the user prompt as gen_ai.input.messages, not the full model input, because the root span exports only at turn close.
  • status_code: UNSET on a successful span is correct. OTel reserves Ok for explicit developer intent; UNSET is the success default. Failures already route through span.end({ error }), which sets ERROR plus error.type.

Verifying traces

Agent spans go to the W&B Agents store at https://trace.wandb.ai/agents/otel/v1/traces, which is separate from classic Weave calls. The weave-calls MCP tools read 0 from it even when the project is full, so query the agents endpoints directly:

curl -s -u "api:$WANDB_API_KEY" -X POST https://trace.wandb.ai/agents/spans/query \
  -H 'Content-Type: application/json' \
  -d '{"project_id":"<entity>/<project>","limit":50,"include_details":true,
       "sort_by":[{"field":"started_at","direction":"desc"}]}'

Three request-shape traps that produce believable but wrong conclusions:

  • sort_by must be a list of {field, direction}. A bare string 422s.
  • Tool payload columns (tool_call_arguments, tool_call_result, tool_type) populate only with include_details: true. Without it they read empty, which looks exactly like the client failing to record them.
  • raw_span_dump.attributes comes back nested, because the server parses JSON-string attribute values. Recursively flattening it turns one wire attribute (gen_ai.tool.call.arguments) into many dotted sub-keys (gen_ai.tool.call.arguments.command). Do not infer the wire format from a flattened view.

Span names carry their target (invoke_agent claude-code, execute_tool Bash, chat <model>), so select spans by operation_name, not span_name.

Here tracing is imported from @coreweave/forge-sdk/agentlens/tracing.

For an end-to-end check, drive the real Daemon with the real OTLP exporter (tracing.init(project) with no span-processor override), route synthetic hook events through routeEvent, await tracing.forceFlush(), then read the spans back with the query above. tests/helpers.ts has the in-memory equivalent for unit tests.

Export failures are invisible by default: a bad key or an unwritable project drops every span while hooks keep succeeding and the log rotates. Before trusting an empty project, grep the daemon log for OTLPExporterError. Surfacing the last rejection through forge-agent-lens-for-claude-code status is in flight on feat/status-export-health.

Transcript lifecycle

Claude Code creates the session transcript after SessionStart, so any hook that fires early can see a path that does not exist yet. TranscriptFile.getFd() throws in that window and caches the fd once it succeeds.

Read through Session.parseTranscript(), which treats an unreadable transcript as empty. A bare parseSessionFd(this.transcript.getFd()) in a turn-creation path lets ENOENT escape to the dispatcher and drops the whole hook, which is how the first prompt of every new session went untraced.

Config

resolveApiKey and resolveProject in src/config.ts prefer the environment over settings.json. A revoked key in settings.json therefore stays hidden as long as WANDB_API_KEY is exported, and only surfaces for anything launched without it. forge-agent-lens-for-claude-code status prints which source won.

The daemon inherits the environment of whatever spawned it, so a daemon started from a shell without WANDB_API_KEY resolves a different key than your terminal does. ps eww -p <pid> shows what it actually got.

Known gaps

  • No content gate or redactor. Tool arguments, tool results, prompts and model output are written to spans raw. A Bash step that prints a credential puts that credential in gen_ai.tool.call.result.stdout. Any payload capture added here inherits that exposure until a gate lands.
  • chat spans carry gen_ai.agent.name but not gen_ai.agent.version. agent_name is the join key, so attribution works without it.

Checks

npm run check runs tsc then the full suite. Run it before pushing. Tests live in tests/ mirroring src/, grouped per concern rather than per fix.

Download now (ZIP)

  • Other versions3 projects use a version of this.

    Word for word · 3

    1. wandb/forge-agent-lens-for-claude-code★ 9100% same
    2. wandb/forge-claude-code★ 9100% same
    3. wandb/weave-claude-code★ 9100% same

    Edited · 0

    None found.

    Wrote their own version · 0

    None found.

    How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.

  • Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.

    Of the AGENTS.md files we read, the 28,693 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.

  • In this repository4 other files it gives its agents.

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

Reviews can't be read right now.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.