소스 정보
- 저장소
- Datus-ai/Datus-agent
- 최근 소스 활동
- 2026년 8월 13일 06:25
- 감지된 SKILL.md 언어
- 영어
- 스타
- 1,558
- 포크
- 228
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
메뉴
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/Datus-ai/Datus-agent --skill gen-metrics명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
SOC 직업 분류 기준
SKILL.md 표시 중
| name | gen-metrics |
| description | Generate MetricFlow metrics from natural language business descriptions |
| tags | ["metrics","metricflow"] |
| version | 1.3.0 |
| user_invocable | false |
| disable_model_invocation | false |
| allowed_agents | ["gen_metrics"] |
Guide the user through metric generation using natural language business descriptions.
Use SQL supplied with the request directly. For an explicitly named readable workspace SQL file, call read_file once. Interpret the complete SQL together with the user's business intent, the live target YAML, and the metric catalog when deciding reuse, datasets, and expressions.
Only inspect and edit semantic model YAML files under the current datasource directory shown in the system prompt, such as subject/semantic_models/<current_datasource>/.... Do not reuse or sync YAML files from sibling datasource directories; those files are outside the active MetricFlow adapter scope.
Analyze the user's request and confirm the generation scope before proceeding. When ask_user is available, call it to confirm the metric name(s), business meaning, and calculation logic. When ask_user is not available (for example workflow or batch mode), infer from the provided SQL/request and stop only if the scope is materially ambiguous.
Step 1a: Inspect the table — Call describe_table(table_name) to understand the columns and types. Optionally call execute_sql(sql="SELECT * FROM <table> LIMIT 5") to sample data.
Step 1b: Ask for reference SQL (optional) — When ask_user is available, use it to ask:
"Do you have any existing SQL queries for this table that show the aggregations you care about? You can paste them here, or skip if not available."
When ask_user is not available, skip this question and infer SQL/aggregation context from the user's request, attached files, or discovered query/table evidence. If that is not enough, stop and explain the missing information instead of calling ask_user.
If the user provides SQL, use it to identify:
SUM(amount) / COUNT(DISTINCT user_id) AS arppu → candidate metric arppu)SUM(amount) → candidate measure total_amount, COUNT(*) → candidate measure record_count)If the provided SQL contains no metric-producing output, keep filter-only or detail-query evidence as filters, dimensions, segments, or view evidence instead of generating fake metrics.
If the user skips, proceed to Step 1c using only table structure and the user's description.
Step 1c: Propose metric candidates — Based on the table structure, reference SQL (if provided), and user's request, identify potential metric scenarios. See "Metric type detection rules" below.
Step 1d: Confirm scope — when ask_user is available, call it to confirm and present proposed metrics with multi_select: true (see Step 1-batch-d for format). If ask_user is not available, proceed with the confirmed/inferred scope from the input.
Step 1-batch-a: Collect SQL queries
read_file once.describe_table for each unique table found in the SQL queriesStep 1-batch-b: Interpret reusable semantics
Step 1-batch-c: Business metric principle
From N SQL queries, propose a focused set of business metrics. Ask yourself for each candidate:
Step 1-batch-d: Confirm with the user when possible
ask_user is available, present the mined business metric candidates as options with multi_select: truequestions as an actual array argument, not a JSON string. Example tool arguments:
{
"questions": [
{
"title": "Metrics",
"question": "I analyzed N SQL queries and identified the following metric candidates. Select which ones to generate:",
"options": ["paid_arppu - SUM(paid_amount) / COUNT(DISTINCT user_id)", "gross_margin_rate - (SUM(revenue) - SUM(cost)) / SUM(revenue)"],
"multi_select": true
}
]
}
ask_user is not available, proceed with the mined metrics only if the input makes the scope unambiguous; otherwise stop and explain what needs to be provided.measure_proxy metric referencing that measure by stringmeasure_proxy metric referencing that measure by stringratio typeexpr type combining measuresderived type combining metricscumulative typeDetection keywords:
gen_sqlIMPORTANT: Do NOT proceed to Phase 2 with materially ambiguous scope. Use ask_user when available; otherwise stop and explain what information is needed.
For each table involved in the metric:
check_semantic_object_exists(name="{table_name}", kind="table") to check if a semantic model exists.read_file to read the existing semantic model YAMLedit_file to add them, then validate_semanticIf the semantic model is missing, follow the metricflow-semantic-authoring workflow when that skill is available. In brief: call inspect_semantic_sources with all required physical tables, then use the live schemas, request-SQL field usage, and relationship candidates to write semantic model YAML under the directory shown in the system prompt. Run validate_semantic and fix issues until it passes before continuing.
When the metric involves multiple tables (detected from JOIN in SQL or user description), choose the modeling strategy based on SQL complexity:
Strategy A: Identifier-based JOIN (default — use when possible)
Use when: simple equi-JOIN between 2-3 tables via foreign keys, ≤ 2 JOIN hops.
data_source with sql_tableidentifiers (same name, one PRIMARY, one FOREIGN)inspect_semantic_sources.relationships to set up correct identifier linkagesorders.customer_id (FOREIGN) links to customers.customer_id (PRIMARY) — both identifiers share name: customerStrategy B: sql_query pre-joined data source (complex cases)
Use when: non-equi JOINs, > 2 hop joins, subqueries, LATERAL/CROSS joins, complex ON conditions, or window functions in the JOIN.
data_source with sql_query containing the pre-joined SQLdata_source:
name: order_customer_summary
sql_query: |
SELECT o.order_id, o.amount, o.order_date,
c.name as customer_name, c.segment
FROM schema.orders o
JOIN schema.customers c ON o.customer_id = c.id
measures:
- name: total_revenue
agg: SUM
expr: amount
dimensions:
- name: customer_name
type: CATEGORICAL
- name: order_date
type: TIME
type_params:
is_primary: true
time_granularity: DAY
Decision rule: Default to Strategy A. Use it when the join can be represented as identifier-level keys (single-column or derived expressions). Use Strategy B for composite multi-column equi-joins unless they are represented in source SQL as a derived key expression, and for non-equi conditions, 3+ hop joins, or subquery-based logic.
File paths: All write_file / edit_file / read_file calls use paths relative to the filesystem sandbox root. Always use the semantic model directory shown in the system prompt so subsequent reads find the file. For example:
subject/semantic_models/<current_datasource>/{table_name}.ymlsubject/semantic_models/<current_datasource>/metrics/{table_name}_metrics.ymlBare filenames are silently normalized by the host, but the prefixed form is preferred for clarity. Absolute paths are also tolerated.
Do not read, edit, or pass metric_file / semantic_model_files paths from another datasource directory such as subject/semantic_models/other_datasource/....
Check existing: Call check_semantic_object_exists(name="{metric_name}", kind="metric") for each metric confirmed in Phase 1. If it already exists, inform the user and skip it.
Write metric YAML: Use write_file to save each metric definition to subject/semantic_models/<current_datasource>/metrics/{table_name}_metrics.yml.
measure_proxy, keep type_params.measure as a string measure name.metric: YAML document. Do not emit unnamed metric: blocks or wrap metrics inside another object.Validate (MUST PASS): Call validate_semantic to check the metric YAML.
edit_file and retry until it passes.After all generated metrics have passed validation:
publish_metrics(metric_file) once to sync it to Knowledge Base while you can still fix publish errors.publish_metricsPhase 1 confirms the generation scope; validation is the semantic acceptance gate before syncing.
Explicit metric files: Write explicit metric YAML files under the semantic model directory's metrics/ subdirectory instead of relying on create_metric: true. Runtime-generated metrics are not part of the persisted metric catalog.
Metric name must match measure name: For a measure_proxy metric, the metric name should typically equal the measure name (or be a clear derivative). The type_params.measure must exactly match a measure name from the semantic model. Do NOT invent unrelated names (e.g., measure activity_count → metric name should be activity_count, NOT total_activity_count or activity_count_metric).
Filtered metrics: Model reusable filter logic as a conditional measure in the semantic model, such as expr: "CASE WHEN status = 'completed' THEN 1 ELSE 0 END" with agg: SUM, then write type_params.measure: completed_order_count in the metric YAML.
Check before creating: ALWAYS call check_semantic_object_exists(name="{metric_name}", kind="metric") before writing a new metric. If the metric already exists, skip it.
Verify the artifact after validation: Ensure each metric_file points to validated metric YAML before calling publish_metrics(metric_file). Do not pass output bindings.
Every metric needs explicit YAML: Whether it's a simple aggregation, filtered variant, ratio, expr, derived, or cumulative — write a metric: entry in the metrics YAML file so it can be persisted and discovered later.
Derived metrics are second-stage: Generate and validate input metrics first. Author a derived metric only when every referenced metric exists in the live target or was generated earlier in the same run.
Support measures are not always metrics: Add support measures needed for ratios, expressions, filters, and validation, but do not publish each support measure as a separate metric unless it is itself a requested/final business KPI.
measure_proxy (simple aggregation):
metric:
name: {metric_name}
description: "{description}"
type: measure_proxy
type_params:
measure: {measure_name}
locked_metadata:
tags:
- "{category}"
- "subject_tree: {domain}/{layer1}/{layer2}"
For a filtered metric, define a dedicated conditional measure in the semantic model and keep the metric's type_params.measure as a string:
data_source:
name: orders
measures:
- name: completed_order_count
description: "Completed order count"
agg: SUM
expr: "CASE WHEN status = 'completed' THEN 1 ELSE 0 END"
---
metric:
name: completed_order_count
description: "Completed order count"
type: measure_proxy
type_params:
measure: completed_order_count
ratio (ratio of two measures):
metric:
name: {metric_name}
description: "{description}"
type: ratio
type_params:
numerator: {measure_or_metric_name}
denominator: {measure_or_metric_name}
locked_metadata:
tags:
- "subject_tree: {domain}/{layer1}/{layer2}"
expr (expression combining measures):
metric:
name: {metric_name}
description: "{description}"
type: expr
type_params:
measures:
- measure_a
- measure_b
expr: "{expression}" # e.g. "(measure_a - measure_b) / measure_a"
locked_metadata:
tags:
- "subject_tree: {domain}/{layer1}/{layer2}"
derived (expression combining existing metrics):
metric:
name: {metric_name}
description: "{description}"
type: derived
type_params:
metrics:
- name: metric_a
# Optional: period-over-period comparison
alias: metric_a_prev
offset_window: 1 week # compare to 1 week ago (WoW)
- name: metric_b
offset_to_grain: month # compare to start of current month (MTD)
expr: "{expression}" # e.g. "metric_a / metric_a_prev"
locked_metadata:
tags:
- "subject_tree: {domain}/{layer1}/{layer2}"
Period-over-period example — a MoM SQL whose final output is metric_a_mom_delta should publish a fixed MoM delta metric, not a query-time compare instruction and not a previous-value helper unless that helper is itself the final requested output:
metric:
name: metric_a_mom_delta
description: "{metric_a month-over-month delta description}"
type: derived
type_params:
metrics:
- name: metric_a
- name: metric_a
alias: metric_a_prev
offset_window: 1 month
expr: "metric_a - metric_a_prev"
cumulative (running total over time):
metric:
name: {metric_name}
description: "{description}"
type: cumulative
type_params:
measure: {measure_name}
# Use ONE of:
window: {time_window} # rolling window, e.g. "7 days", "1 month"
grain_to_date: month|year # MTD/YTD - resets at grain boundary
locked_metadata:
tags:
- "subject_tree: {domain}/{layer1}/{layer2}"
Ordinary period-over-period SQL (LAG, previous period, DoD/WoW/MoM/QoQ/YoY, delta, or rate) is fixed long-term metric evidence when it is a final business output: monthly YoY is distinct from weekly YoY, MoM rate is distinct from MoM delta, and previous-period value is distinct from a rate. Publish a previous-period metric only when it is itself the requested final output.
ask_user when it is available.validate_semantic and ensure it passes before proceeding to the next phase. If it fails, fix and retry until it passes.publish_metrics without another user confirmation; the final JSON metric_file is only a last-resort fallback.expr: "1" — never use expr: {column} with COUNT (use COUNT_DISTINCT for that).non_additive_dimension to prevent incorrect time aggregation.publish_metrics; the final JSON metric_file is only a last-resort fallback.