Implement observability for Lindy AI integrations. Use when setting up monitoring, logging, tracing, or building dashboards for Lindy operations. Trigger with phrases like "lindy monitoring", "lindy observability", "lindy metrics", "lindy logging", "lindy tracing".
/plugin marketplace add jeremylongshore/claude-code-plugins-plus-skills/plugin install lindy-pack@claude-code-plugins-plusThis skill is limited to using the following tools:
Implement comprehensive observability for Lindy AI integrations.
// lib/logger.ts
import pino from 'pino';
export const logger = pino({
level: process.env.LOG_LEVEL || 'info',
formatters: {
level: (label) => ({ level: label }),
},
base: {
service: 'lindy-integration',
environment: process.env.NODE_ENV,
},
});
// Lindy-specific logger
export function lindyLogger(operation: string) {
return logger.child({ component: 'lindy', operation });
}
// lib/instrumented-lindy.ts
import { Lindy } from '@lindy-ai/sdk';
import { lindyLogger } from './logger';
import { metrics } from './metrics';
import { tracer } from './tracer';
export class InstrumentedLindy {
private lindy: Lindy;
constructor() {
this.lindy = new Lindy({ apiKey: process.env.LINDY_API_KEY });
}
async runAgent(agentId: string, input: string) {
const log = lindyLogger('runAgent');
const span = tracer.startSpan('lindy.agent.run');
const startTime = Date.now();
try {
span.setAttributes({
'lindy.agent_id': agentId,
'lindy.input_length': input.length,
});
log.info({ agentId, inputLength: input.length }, 'Starting agent run');
const result = await this.lindy.agents.run(agentId, { input });
const duration = Date.now() - startTime;
// Record metrics
metrics.histogram('lindy.agent.duration', duration, { agentId });
metrics.counter('lindy.agent.success', 1, { agentId });
// Log success
log.info({
agentId,
duration,
outputLength: result.output.length,
}, 'Agent run completed');
span.setAttributes({
'lindy.duration_ms': duration,
'lindy.output_length': result.output.length,
'lindy.status': 'success',
});
return result;
} catch (error: any) {
const duration = Date.now() - startTime;
// Record error metrics
metrics.counter('lindy.agent.error', 1, {
agentId,
errorCode: error.code,
});
// Log error
log.error({
agentId,
duration,
error: error.message,
errorCode: error.code,
}, 'Agent run failed');
span.setAttributes({
'lindy.status': 'error',
'lindy.error': error.message,
});
span.recordException(error);
throw error;
} finally {
span.end();
}
}
}
// lib/metrics.ts
import { Counter, Histogram, Registry } from 'prom-client';
const registry = new Registry();
export const metrics = {
agentDuration: new Histogram({
name: 'lindy_agent_duration_ms',
help: 'Duration of Lindy agent runs in milliseconds',
labelNames: ['agent_id', 'status'],
buckets: [100, 500, 1000, 2000, 5000, 10000, 30000],
registers: [registry],
}),
agentRuns: new Counter({
name: 'lindy_agent_runs_total',
help: 'Total number of Lindy agent runs',
labelNames: ['agent_id', 'status'],
registers: [registry],
}),
apiCalls: new Counter({
name: 'lindy_api_calls_total',
help: 'Total Lindy API calls',
labelNames: ['endpoint', 'status'],
registers: [registry],
}),
// Helper methods
histogram(name: string, value: number, labels: Record<string, string>) {
const metric = registry.getSingleMetric(name) as Histogram;
metric?.observe(labels, value);
},
counter(name: string, value: number, labels: Record<string, string>) {
const metric = registry.getSingleMetric(name) as Counter;
metric?.inc(labels, value);
},
};
// Metrics endpoint
export function getMetrics(): Promise<string> {
return registry.metrics();
}
// lib/tracer.ts
import { trace, SpanStatusCode } from '@opentelemetry/api';
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
const provider = new NodeTracerProvider();
provider.addSpanProcessor(
new SimpleSpanProcessor(
new OTLPTraceExporter({
url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT,
})
)
);
provider.register();
export const tracer = trace.getTracer('lindy-integration');
# grafana/dashboards/lindy.json
{
"title": "Lindy AI Monitoring",
"panels": [
{
"title": "Agent Runs per Minute",
"type": "graph",
"targets": [
{
"expr": "rate(lindy_agent_runs_total[1m])",
"legendFormat": "{{agent_id}}"
}
]
},
{
"title": "P95 Latency",
"type": "stat",
"targets": [
{
"expr": "histogram_quantile(0.95, rate(lindy_agent_duration_ms_bucket[5m]))"
}
]
},
{
"title": "Error Rate",
"type": "graph",
"targets": [
{
"expr": "rate(lindy_agent_runs_total{status='error'}[5m]) / rate(lindy_agent_runs_total[5m])"
}
]
}
]
}
| Issue | Cause | Solution |
|---|---|---|
| Missing traces | OTEL not configured | Set OTEL endpoint |
| Metrics not visible | Wrong labels | Check label names |
| Logs not searchable | Missing context | Add structured fields |
# alerts/lindy.yml
groups:
- name: lindy
rules:
- alert: LindyHighErrorRate
expr: rate(lindy_agent_runs_total{status="error"}[5m]) > 0.1
for: 5m
labels:
severity: critical
annotations:
summary: "High Lindy error rate"
- alert: LindyHighLatency
expr: histogram_quantile(0.95, rate(lindy_agent_duration_ms_bucket[5m])) > 10000
for: 5m
labels:
severity: warning
annotations:
summary: "Lindy P95 latency above 10s"
Proceed to lindy-incident-runbook for incident response.
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.
Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.
Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.