Skip to content

Add support for custom tags via CC_LANGFUSE_TAGS - #37

Open
choonchernlim wants to merge 1 commit into
langfuse:mainfrom
choonchernlim:main
Open

Add support for custom tags via CC_LANGFUSE_TAGS#37
choonchernlim wants to merge 1 commit into
langfuse:mainfrom
choonchernlim:main

Conversation

@choonchernlim

Copy link
Copy Markdown

Add support for custom tags via CC_LANGFUSE_TAGS

Summary

Adds an optional CC_LANGFUSE_TAGS environment variable that lets users append custom, static tags to every trace produced by the Langfuse hook - useful for filtering/grouping traces by environment, team, project, etc. in Langfuse. This is very similar to Codex's LANGFUSE_CODEX_TAGS (link)

Changes

  • hooks/langfuse_hook.py: Reads CC_LANGFUSE_TAGS as a comma-separated list, trims whitespace, and drops empty entries. The resulting CUSTOM_TAGS list is appended to the base "claude-code" tag in get_trace_tags(), before any
    skill-derived tags.
  • .claude-plugin/plugin.json: Registers CC_LANGFUSE_TAGS as an optional string config option with a title and description.
  • README.md: Documents the new environment variable in the configuration table.
  • tests/unit/test_skill_tags.py: Adds coverage for:
    • Custom tags being appended to every trace.
    • No custom tags leaving trace tags unchanged (backwards-compatible default).
    • Custom tags combining correctly with skill-derived tags.

Usage

CC_LANGFUSE_TAGS=env:prod,team:platform                                                                                                                                                                                                      

Every trace will then be tagged ["claude-code", "env:prod", "team:platform", ...], with any skill tags appended after.

Test plan

  • pytest tests/unit/test_skill_tags.py - all new and existing tests pass
  • Verified default behavior (no CC_LANGFUSE_TAGS set) leaves trace tags unchanged

@atoomic

atoomic commented Aug 18, 2026

Copy link
Copy Markdown

Hi @choonchernlim — I needed this exact capability and ended up building on your PR, so credit where it's due: the option name, the placement in get_trace_tags() and even the make_plain_assistant_row test helper here are yours.

I've opened #61 as a superset, and filed #62 for the underlying need. Four gaps it closes, in case you'd rather fold them in here — I'd genuinely prefer that, and would close mine:

  1. No dedup. CC_LANGFUSE_TAGS=claude-code currently doubles the base tag, and a value repeating a skill:* tag doubles that one. list(dict.fromkeys(tags)) on the return fixes it and is a no-op for every other input.
  2. No bounds. A tag over 200 chars is silently dropped by the SDK itself, so the operator never learns why it vanished. Capping locally at the same 200 (and at 20 tags) means a tag the hook accepts is never dropped again downstream, and a rejected one gets a log line.
  3. The inline comprehension can't be tested at the parse level — which is, I think, why the tests here cover composition but not parsing. Pulling it into a named parse_custom_tags() makes the empty/whitespace/dedup/cap cases directly assertable.
  4. CC_LANGFUSE_SKILL_TAGS=false is untested. Your placement already handles it correctly (the append is outside the if SKILL_TAGS block) — it just isn't pinned by a test, so a future refactor could move it inside without anything failing.

One thing I hit that isn't obvious: if you add a warning for malformed input, it can't be logged from the constant. CUSTOM_TAGS is evaluated at import time, before info() and _get_logger() exist — and _get_logger() swallows exceptions, so an inline log call there doesn't crash, it silently does nothing. _resolve_state_dir() already solves this by returning (value, warning) and letting main() emit it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants