Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Maple Onboarding Style

ASecurity

General OpenTelemetry onboarding style for Maple: native APIs, the business-span pattern, signal quality, inline keys, VCS resource attributes, LLM calls, and smoke checks.

1,799 stars
0 votes
0 copies
0 views
Added 10/1/2026
developmentjavascripttypescriptpythongojavashellnodetestinggitapi

Works with

cliapi

Security Analysis

A100/100

Scanned 10/1/2026

$npx -y skills add MapleTechLabs/maple --skill maple-onboarding-style --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Maple Onboarding Style?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Maple Onboarding Style
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/mapletechlabs-maple-onboarding-style/badge)](https://www.skillsdirectory.com/skills/mapletechlabs-maple-onboarding-style)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
Files
SKILL.md
---
name: maple-onboarding-style
description: "General OpenTelemetry onboarding style for Maple: native APIs, the business-span pattern, signal quality, inline keys, VCS resource attributes, LLM calls, and smoke checks."
---

# Maple OTel onboarding style

Use native OpenTelemetry APIs. Do not invent helper APIs.

## Business spans in TypeScript/JavaScript

Use `tracer.startActiveSpan` with `try` / `catch` / `finally`: record the exception and set `Error` status before rethrowing, and end the span in `finally`. The callback form keeps the span active for everything inside it, in browsers too, and keeps the function sync or async as it was. Don't hide this behind a local helper (`withSpan`, `traced`, …). Don't add spans around provider SDK calls that OpenInference / provider instrumentation already observes.

Do:

```ts
import { metrics, SpanStatusCode, trace } from "@opentelemetry/api"

const tracer = trace.getTracer("orders.api")
const meter = metrics.getMeter("orders.api")
const ordersSubmitted = meter.createCounter("orders.submitted")

export async function submitOrder(tenantId: string, orderId: string) {
	return tracer.startActiveSpan("order.submit", async (span) => {
		try {
			span.setAttributes({ "tenant.id": tenantId, "order.id": orderId })
			const receipt = await chargeOrder(orderId)
			ordersSubmitted.add(1, { "tenant.id": tenantId, outcome: "success" })
			return receipt
		} catch (err) {
			span.recordException(err as Error)
			span.setStatus({ code: SpanStatusCode.ERROR, message: (err as Error).message })
			ordersSubmitted.add(1, { "tenant.id": tenantId, outcome: "failure" })
			throw err
		} finally {
			span.end()
		}
	})
}
```

Do not:

```ts
await sendMapleSpan(...)
recordCounter(...)
withTelemetry(...)
```

## Naming

- Files/functions are provider-neutral: `telemetry.ts`, `observability.ts`, `initTelemetry()`, `initObservability()`.
- The word Maple belongs only in endpoint/key setup comments or PR instructions.
- Span names are conventional and low-cardinality: `checkout.process`, `support.reply`, `llm.summarize_ticket`.
- Prefer semantic product-operation span names over provider transport names. `llm.summarize_ticket` is more useful than `llm.anthropic.messages.create`.

## Endpoint and key

Inline the endpoint and the ingest key directly in the bootstrap source and pass them explicitly to the exporter: its own URL option (`url` in JavaScript, `endpoint` in Python; each language skill shows the exact shape) plus `headers`. Don't read `OTEL_EXPORTER_OTLP_*` env vars and don't write `.env` files. `maple-onboard` Step 0 decides the region and which key goes where.

```text
MAPLE_ENDPOINT = "https://ingest.maple.dev"   # EU organizations: https://ingest.eu.maple.dev
MAPLE_KEY      = "maple_pk_…"                 # public ingest key, or "MAPLE_TEST" until the user has one
```

`MAPLE_TEST` is accepted by both regions and dropped, so the bootstrap exercises the full code path before the real key arrives.

If the repo can call telemetry init from multiple paths, guard provider/exporter setup so repeated imports, tests, reloads, or framework callbacks do not install duplicate processors or log handlers. For a single-entrypoint app that starts cleanly, keep this simple.

Set these resource attributes on every service: `service.name` (the app's own name, e.g. its package name without the scope), `service.version` (the package.json version, a release tag, or the commit SHA), `deployment.environment.name`, and the VCS attributes below.

## VCS resource attributes

Set `vcs.repository.url.full` on the OTel resource for every instrumented server-side service. The value is the canonical https URL of the repo (e.g. `https://github.com/acme/api`): the URL the user would paste in a browser, not an SSH URL or a local working-tree path. This is the important one; it lets Maple link telemetry back to the source. It is fine to hardcode this string alongside `service.name` in the SDK init; if a build env already exposes the slug (e.g. `VERCEL_GIT_REPO_OWNER` + `VERCEL_GIT_REPO_SLUG`, `RAILWAY_GIT_REPO_OWNER` + `RAILWAY_GIT_REPO_NAME`), prefer reading from env so a fork or rename doesn't drift. `@maple-dev/browser` has no option for it; that is fine.

Also set `vcs.ref.head.revision` (the commit SHA) on a best-effort basis. Read it from whatever env var the runtime/build platform already injects: `VERCEL_GIT_COMMIT_SHA`, `RAILWAY_GIT_COMMIT_SHA`, `GITHUB_SHA`, `SOURCE_COMMIT`, `GIT_COMMIT`, `HEROKU_SLUG_COMMIT`, etc. Do not shell out to `git` from the running process. Many production images have no git binary or working tree. If no env source is available, omit the attribute; skipping the SHA is fine, skipping the URL is not. (`@maple-dev/browser` sets it from `serviceVersion` when that is a commit SHA.)

Use `vcs.repository.url.full` and `vcs.ref.head.revision` exactly as named. These are the OTel semantic-convention keys. Do not invent parallel attributes like `git.repo`, `app.repo_url`, or `deployment.commit_sha`.

## Signals

- Traces: all critical operations have spans with relevant attributes.
- Logs: structured, concise, OTLP-forwarded, and trace/span-correlated.
- Metrics: critical operations have low-cardinality counters/histograms.
- Tenant/org/project information is included where available.
- Do not put raw user ids or request ids in metric tags unless the repo already treats them as bounded tenant-like ids.

## LLM calls

If the app uses LLMs, first look for provider instrumentation that already captures model/provider/token/error spans. In JavaScript/TypeScript, prefer OpenInference packages such as `@arizeai/openinference-instrumentation-anthropic` or `@arizeai/openinference-instrumentation-openai` for supported SDKs. Keep the real provider call native and readable.

In Node, `getNodeAutoInstrumentations()` already includes `@opentelemetry/instrumentation-openai` (OTel `gen_ai.*` spans for the `openai` SDK). Use it for OpenAI and don't add OpenInference's OpenAI package as well, or every call is recorded twice. Check each instrumentation's supported SDK range against the installed SDK version: a mismatch installs cleanly and records nothing. Under ESM, OpenInference instrumentations need `manuallyInstrument(<the SDK module>)`.

```ts
const response = await client.messages.create({
	model,
	max_tokens: 100,
	messages,
})
```

Let provider instrumentation own model/provider/token spans where it supports them. Do not duplicate those attributes at every application call site. Where no provider instrumentation exists, put `gen_ai.*` semantic-convention attributes (`gen_ai.provider.name`, `gen_ai.request.model`, `gen_ai.usage.input_tokens`, `gen_ai.usage.output_tokens`) on the span that makes the call, plus `app.gen_ai.*` for bounded application dimensions such as use case and call site. Avoid inventing parallel `llm.*` attributes unless the repo already standardizes on them.

Token counters are only for usage provider instrumentation cannot capture:

```ts
llmInputTokens.add(inputTokens, {
	"tenant.id": tenantId,
	"gen_ai.provider.name": "anthropic",
	"gen_ai.request.model": model,
	"app.gen_ai.use_case": "support.reply",
	"app.gen_ai.call_site": "generateReply",
	outcome: "success",
})
```

Name them `llm.tokens.input` / `llm.tokens.output` with unit `{token}`. Use histograms for latency/duration distributions.

**Cost.** Maple does not price tokens. It shows LLM cost only when a span carries `gen_ai.usage.cost` (USD); without it, Agent Sessions shows token counts and no cost. Set `gen_ai.usage.cost` when the provider returns the billed amount (OpenRouter returns `usage.cost` when the request sets `usage: { include: true }`; adding that flag is in scope). Record only that billed amount; leave cost unset when all you have is the app's own estimate. Put it on the span that makes the call when your code owns that span. When an instrumentation owns it, the span has ended before your code sees the response, so put the cost on the span that wraps the turn: it counts toward the session's cost, though not toward the per-model breakdown. Don't add a price table just for telemetry: prices change and a stale table reports wrong numbers. No `llm.cost_usd`-style metrics.

**Conversations.** Agent Sessions groups traces into one session by `maple_ai.session.id`. For a plain app (direct SDK calls, OpenInference, hand-written `gen_ai.*` spans), set `maple_ai.session.id` to the conversation or thread id on the span that wraps each turn, and `gen_ai.conversation.id` to the same value. Without it every trace is its own session. Agent frameworks that Maple recognizes (OpenAI Agents SDK, Mastra, Pydantic AI, Google ADK, CrewAI, …) emit their own session key; don't add one there. Use an opaque id, never an email or user name.

OpenInference `hideInputs` / `hideOutputs` keep prompts and completions out of telemetry. That is the safe default, but Agent Sessions then shows timing and tokens without a transcript. Tell the user which one you picked.

If the app has OpenAI, Anthropic, and Google callers, instrument all three.

## Smoke checks

Add a durable smoke path when the repo has a natural place for it: README, TESTING guide, script, npm command, pytest, or checked-in command note. If it has none, skip it; the Step 4 run is enough.

The smoke should explicitly prove startup/import with the OTel bootstrap loaded so provider setup, exporter construction, log bridging, and framework instrumentation initialize without errors. Then, where practical, exercise an actual instrumented span/log/metric or OTLP export attempt. A generic health route only proves the server responds; prefer an operation that crosses the instrumentation you added.

Attribution

MapleTechLabsMapleTechLabs
View sourceSee grades on GitHubMore from MapleTechLabs →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Clean Code

Pragmatic coding standards - concise, direct, no over-engineering, no unnecessary comments

304955 votes

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

286712 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2222 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Writing Plans

Use when you have a spec or requirements for a multi-step task, before touching code

2927051 votes
View all in development →