superloglabs/skills

otel-livekit-style

LiveKit Agents OpenTelemetry style: entrypoint/session lifecycle spans, shutdown callbacks, session metrics, and LLM turn token counters.

First seen May 8, 2026

Installation

$ npx skills add superloglabs/skills --skill otel-livekit-style

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from superloglabs/skills · top by installs.

npx skills add superloglabs/skills

Browse all from superloglabs/skills

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 13
License LICENSE
Default branch main
Open issues 0
Status Active

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 3,193 B
  • docs SUMMARY.md 163 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 375 installs

SKILL.md

OTel LiveKit Style

LiveKit session lifecycle begins in entrypoint(ctx) and cleanup ends in ctx.addshutdowncallback(on_shutdown).

Whole-Session Span

It is okay for a voice.session span to end in on_shutdown, because the operation crosses a framework callback boundary. Make it active while child work is registered and started.

async def entrypoint(ctx: agents.JobContext) -> None:
    await ctx.connect()
    started_at = asyncio.get_running_loop().time()
    session_span = tracer.start_span(
        "voice.session",
        attributes={
            "tenant.id": tenant_id,
            "user.id": user_id,
            "voice.room_name": room_name,
        },
    )

    with trace.use_span(session_span, end_on_exit=False):
        voice_sessions_started.add(1, {
            "tenant.id": tenant_id,
            "voice.room_name.present": room_name != "unknown",
        })

        async def on_shutdown() -> None:
            duration_ms = int((asyncio.get_running_loop().time() - started_at) * 1000)
            session_span.set_attribute("voice.duration_ms", duration_ms)
            voice_session_duration.record(duration_ms, {
                "tenant.id": tenant_id,
                "voice.disconnect_reason": disconnect_reason,
                "outcome": "success",
            })
            session_span.end()

        ctx.add_shutdown_callback(on_shutdown)
        await _deliver_initial_greeting(...)

Do not replace this with a short voice.session.end span inside shutdown.

Bounded Session Work

Bounded operations still get their own decorators.

@tracer.start_as_current_span("voice.deliver_initial_greeting")
async def _deliver_initial_greeting(...):
    ...

Session Metrics

Use both:

  • voice.sessions.started counter at entrypoint start
  • voice.session.duration_ms histogram in shutdown

Add product metrics for important voice events, e.g. voice.greetings.delivered.

Smoke Checks

For a minimal LiveKit fixture, a good smoke path imports the agent and executes one tiny instrumented function or starts a span/log record with a local OTLP endpoint. Checking that tracer/meter objects are non-None is not enough.

LLM Turns

Every LLM provider/call site in the voice agent needs:

  • span around the call
  • token counters (llm.tokens.input, llm.tokens.output)
  • tenant/provider/model/use case/call site/outcome attributes

Do not add llm.cost_usd metrics; Superlog estimates cost centrally from provider/model/token data.

Name the span for the product operation, not the provider transport call. For example, prefer llm.voiceresponse or llm.generatecopy over llm.anthropic.messages.create.

attrs = {
    "tenant.id": tenant_id,
    "llm.provider": "anthropic",
    "llm.model": model,
    "llm.use_case": "voice.initial_greeting",
    "llm.call_site": "_call_mug_copy_llm",
    "outcome": "success",
}
llm_tokens_input.add(input_tokens, attrs)
llm_tokens_output.add(output_tokens, attrs)