maple-agent-tracing-ag…
Trace Agno agents with Maple: installs the OpenInference Agno instrumentor with an OTLP…
Trace Haystack agents with Maple: installs a small Haystack tracer that adds OpenTelemetry GenAI attributes to Haystack's own spans, so each conversation is one Maple Agent Session with transcript, model, tokens, cost and tool failures. Triggers on 'trace my haystack agent',
$ npx -y skills add mapletechlabs/maple --skill maple-agent-tracing-haystack --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/maple-agent-tracing-haystackContext preview
The summary Claude sees to decide when to auto-load this skill.
Trace Haystack agents with Maple: installs a small Haystack tracer that adds OpenTelemetry GenAI attributes to Haystack's own spans, so each conversation is one Maple Agent Session with transcript, model, tokens, cost and tool failures. Triggers on 'trace my haystack agent',
name: maple-agent-tracing-haystack description: "Trace Haystack agents with Maple: installs a small Haystack tracer that adds OpenTelemetry GenAI attributes to Haystack's own spans, so each conversation is one Maple Agent Session with transcript, model, tokens, cost and tool failures. Triggers on 'trace my haystack agent', 'add Maple to haystack', 'agent sessions for haystack', 'OpenTelemetry for haystack'."
Goal: one conversation = one Maple Agent Session, with transcript, model calls, tool calls (failures marked), tokens and (on OpenRouter) cost.
pip install "haystack-ai>=3.2" "opentelemetry-haystack>=1.0" "opentelemetry-sdk>=1.45" "opentelemetry-exporter-otlp-proto-http>=1.45"
Use the repo's package manager (`uv add`, `poetry add`, requirements file). Write this file verbatim as `maple_haystack.py` in the app's package:
"""Haystack tracer that adds the OpenTelemetry GenAI attributes Maple reads."""
import json
import logging
from collections.abc import Iterator
from contextlib import contextmanager
from contextvars import ContextVar
from typing import Any
from haystack.dataclasses import ChatMessage
from haystack_integrations.tracing.opentelemetry import OpenTelemetrySpan, OpenTelemetryTracer
from opentelemetry import trace
from opentelemetry.trace import StatusCode
logger = logging.getLogger(__name__)
_conversation_id: ContextVar[str | None] = ContextVar("maple_conversation_id", default=None)
@contextmanager
def conversation(conversation_id: str) -> Iterator[None]:
"""Every Haystack run inside this block joins the same Maple session."""
token = _conversation_id.set(conversation_id)
try:
yield
finally:
_conversation_id.reset(token)
def _messages(messages: list[ChatMessage]) -> str:
out = []
for m in messages:
parts: list[dict[str, Any]] = [{"type": "text", "content": t} for t in m.texts]
parts += [{"type": "tool_call", "id": c.id, "name": c.tool_name, "arguments": c.arguments} for c in m.tool_calls]
parts += [{"type": "tool_call_response", "id": r.origin.id, "response": r.result} for r in m.tool_call_results]
out.append({"role": m.role.value, "parts": parts})
return json.dumps(out, default=str)
class MapleSpan(OpenTelemetrySpan):
def __init__(self, span: trace.Span, operation: str | None, content: bool) -> None:
super().__init__(span)
self._operation = operation
self._content = content
def set_content_tag(self, key: str, value: Any) -> None:
try:
if self._operation == "chat":
self._chat(key, value)
elif self._operation == "execute_tool":
self._tool(key, value)
except Exception: # a tracing bug must never fail the agent run
logger.exception("maple_haystack: could not map %s", key)
if self._content:
self.set_tag(key, value)
def _chat(self, key: str, value: Any) -> None:
if key.endswith(".input") and self._content:
messages = value["messages"]
system = [{"type": "text", "content": m.text} for m in messages if m.is_from("system")]
if system:
self._span.set_attribute("gen_ai.system_instructions", json.dumps(system))
self._span.set_attribute("gen_ai.input.messages", _messages([m for m in messages if not m.is_from("system")]))
elif key.endswith(".output"):
replies = value["replies"]
meta = replies[0].meta
usage = meta.get("usage") or {}
prompt_details = usage.get("prompt_tokens_details") or {}
attributes = {
"gen_ai.response.model": meta.get("model"),
"gen_ai.response.finish_reasons": meta.get("finish_reason"),
"gen_ai.usage.input_tokens": usage.get("prompt_tokens"),
"gen_ai.usage.output_tokens": usage.Repo: mapletechlabs/maple
Trace Agno agents with Maple: installs the OpenInference Agno instrumentor with an OTLP…
Trace Claude Agent SDK agents (TypeScript and Python) and Claude Code CLI sessions with…
Trace Cloudflare Agents SDK agents (AIChatAgent, Agent on Durable Objects, npm `agents` /…
Trace CrewAI crews and flows with Maple: OpenInference CrewAI instrumentor plus the model-SDK…
Trace DSPy programs and ReAct agents with Maple: OpenInference DSPy instrumentor with GenAI…
Trace Genkit (TypeScript/Node.js) agents with Maple: export Genkit's OpenTelemetry spans to…