Agent Skill
2/7/2026

deploy

Deploy the qyl observability platform. Use when the user says "deploy", "deploy qyl", "push to production", "run qyl", or "go live".

A
ancplua
0GitHub Stars
1Views
npx skills add ANcpLua/qyl

SKILL.md

Namedeploy
DescriptionDeploy the qyl observability platform. Use when the user says "deploy", "deploy qyl", "push to production", "run qyl", or "go live".

qyl

Question Your Logs — AI Observability Platform

Landing page: https://ancplua.github.io/qyl/

What qyl Does

CollectsOTLP receiver with idempotent ingestion (retry-safe)
InstrumentsRoslyn source generators for zero-config GenAI telemetry
VisualizesReal-time dashboard with SSE streaming
IntegratesMCP server and GitHub Copilot for AI agent observability

Tech Stack

LayerTechnology
Runtime.NET 10.0 LTS, C# 14
FrontendReact 19, Vite 7, Tailwind CSS 4
StorageDuckDB (columnar, upsert-based)
ProtocolOpenTelemetry 1.40 GenAI Semantic Conventions
SchemaTypeSpec → OpenAPI → C#/DuckDB/TypeScript

Components

PackagePurpose
qyl.collectorOTLP receiver, DuckDB storage, REST API, embedded dashboard
qyl.copilotGitHub Copilot integration with AG-UI tool rendering
qyl.hostingApp orchestration framework (QylRunner)
qyl.servicedefaults.NET instrumentation library with OTel setup
qyl.servicedefaults.generatorRoslyn source generator for GenAI/DB interceptors
qyl.instrumentation.generatorsDuckDB insert + interceptor source generators
qyl.mcpMCP server for AI agent integration
qyl.protocolShared types (BCL-only, no dependencies)

Quick Start

Hosted

https://qyl-api-production.up.railway.app

Docker

docker build -f src/qyl.collector/Dockerfile -t qyl .
docker run -d -p 5100:5100 -p 4317:4317 -v ~/.qyl:/data qyl

From Source

git clone https://github.com/ANcpLua/qyl.git
cd qyl
dotnet run --project src/qyl.collector

Instrument Your .NET App

Add the service defaults package to automatically instrument GenAI calls:

// Program.cs
builder.AddQylServiceDefaults();

This auto-instruments:

  • IChatClient calls (Microsoft.Extensions.AI)
  • Token usage, latency, model info
  • Full OTel 1.40 GenAI semantic conventions

Set the exporter endpoint:

export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:5100"

Use with Any OTel App

qyl accepts standard OTLP from any language/framework:

# Point any OpenTelemetry SDK at qyl
export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:5100"
export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"

Supported protocols:

  • OTLP/HTTP (port 5100)
  • OTLP/gRPC (port 4317)

Architecture

+------------------+                     +------------------+
|  Your .NET App   |                     |  Any OTel App    |
| (servicedefaults)|                     |  (Python, Go..)  |
+--------+---------+                     +--------+---------+
         |                                        |
         |               OTLP                     |
         +----------------+-----------------------+
                          v
            +----------------------------+
            |       qyl.hosting          |
            |      (QylRunner)           |
            +-------------+--------------+
                          | orchestrates
                          v
            +----------------------------+
            |       qyl.collector        |
            |        (ASP.NET)           |
            +---+------+------+-----+---+
                |      |      |     |
      +---------+  +---+---+  |  +--+--------+
      v            v       v  |  v            v
+----------+ +----------+ |  | +----------+ +----------------+
|  DuckDB  | | Dashboard| |  | |   MCP    | |  qyl.copilot   |
| (storage)| | (React)  | |  | | (agents) | | (GitHub Copilot)|
+----------+ +----------+ |  | +----------+ +-------+--------+
                           |  |                      |
                     +-----+--+-----+          SSE / AG-UI
                     | Insights     |                |
                     | Materializer |                v
                     +--------------+        GitHub Copilot

AG-UI Tool Rendering

qyl.copilot exposes observability tools to GitHub Copilot via SSE streaming with AG-UI event conventions.

Tools (via ObservabilityTools):

ToolDescription
search_spansSearch spans by service name, status, time range
get_traceGet all spans for a trace ID
get_genai_statsGenAI usage statistics (requests, tokens, costs)
search_logsSearch logs by severity, body text, time range
get_storage_statsStorage statistics (span/log/session counts, size)
list_sessionsList spans belonging to a session
get_system_contextPre-computed system context (zero query cost)

Each tool is wrapped by DelegatingAIFunction which applies CopilotMetrics (counters, histograms) and CopilotInstrumentation (OTel spans).

Endpoints:

MethodPathPurpose
POST/api/v1/copilot/chatChat (SSE streaming)
GET/api/v1/copilot/workflowsList workflows
POST/api/v1/copilot/workflows/{name}/runExecute workflow (SSE)
GET/api/v1/copilot/statusAuth status
GET/api/v1/copilot/executionsExecution history
GET/api/v1/copilot/executions/{id}Execution details

SSE events use AG-UI convention: tool_call and tool_result event names.

Insights Materializer

Background service that pre-computes system context every 5 minutes (10-second warmup delay).

MaterializerComputes
TopologyMaterializerService discovery, AI model usage
ProfileMaterializerLatency percentiles (P50/P95/P99), token costs, trends
AlertsMaterializerError spikes, cost drift, slow operations

Results are stored in the materialized_insights table and served via get_system_context with zero query cost at read time.

Ports

PortProtocolPurpose
5100HTTPREST API, Dashboard, OTLP/HTTP
4317gRPCOTLP/gRPC ingestion

Environment Variables

VariableDefaultPurpose
QYL_PORT5100HTTP API port
QYL_GRPC_PORT4317gRPC OTLP port (0=disable)
QYL_DATA_PATH./qyl.duckdbDuckDB file location
QYL_TOKEN(none)Auth token
QYL_MAX_RETENTION_DAYS30Telemetry retention
QYL_MAX_SPAN_COUNT1000000Max spans before cleanup
QYL_MAX_LOG_COUNT500000Max logs before cleanup
QYL_CLEANUP_INTERVAL_SECONDS300Cleanup interval
QYL_OTLP_CORS_ALLOWED_ORIGINS*CORS origins (CSV)

GenAI Telemetry

qyl captures OpenTelemetry 1.40 GenAI semantic conventions:

AttributeDescription
gen_ai.provider.nameProvider (openai, anthropic, etc)
gen_ai.request.modelModel name
gen_ai.usage.input_tokensPrompt tokens
gen_ai.usage.output_tokensCompletion tokens
gen_ai.response.finish_reasonsStop reason

TypeSpec-First Design

All types are defined in TypeSpec and generated downstream:

core/specs/*.tsp
       ↓ (tsp compile)
core/openapi/openapi.yaml
       ↓ (nuke Generate)
   ┌───┴───┬───────┬────────┐
   ↓       ↓       ↓        ↓
  C#    DuckDB    TS    JSON Schema

Never edit *.g.cs or api.ts — edit TypeSpec and regenerate.

Idempotent Ingestion

Spans use ON CONFLICT (span_id) DO UPDATE — SDKs can safely retry on network errors without creating duplicates. Mutable fields (tokens, status, cost) are updated; immutable fields (trace_id, name, start_time) are preserved.

Development

# Full build (TypeSpec → Docker)
nuke Full

# Regenerate types from TypeSpec
nuke Generate --force-generate

# Run tests
dotnet test

# Dashboard dev server (hot reload)
cd src/qyl.dashboard && npm run dev

# Collector only
dotnet run --project src/qyl.collector

Project Structure

core/                                   # TypeSpec schemas (source of truth)
eng/                                    # NUKE build system
src/
  qyl.collector/                        # Backend API service
  qyl.copilot/                          # GitHub Copilot integration (AG-UI)
  qyl.dashboard/                        # React frontend
  qyl.hosting/                          # App orchestration (QylRunner)
  qyl.mcp/                             # MCP server
  qyl.protocol/                         # Shared types (BCL-only)
  qyl.servicedefaults/                  # OTel instrumentation library
  qyl.servicedefaults.generator/        # Roslyn source generator
  qyl.instrumentation.generators/       # DuckDB insert + interceptor generators
tests/                                  # Test projects

License

MIT

Skills Info
Original Name:deployAuthor:ancplua