mcpField
P
profile-investigator

profile-investigator

github.com/lyticsData & databases447 installsUpdated 3w ago
Repository

About profile-investigator

Profile Investigator is a skill for diagnosing Lytics user profiles, segment membership, and data lineage. It compares profile values with segment FilterQL conditions to explain which checks pass or fail.

Key features

  1. 01Fetch full profiles and memberships
  2. 02Evaluate FilterQL conditions
  3. 03Explain segment inclusion or exclusion
  4. 04Trace profile data lineage
  5. 05Summarize profile attributes

Use cases

  1. 01Diagnosing segment membership
  2. 02Finding why a profile misses a segment
  3. 03Tracing the origin of profile data
  4. 04Reviewing a profile and its segments

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/lytics/agent-skills --skill profile-investigator

After installing, type/profile-investigatorin Claude Code to confirm it loaded.

Details

From the project README

Profile Investigator

Purpose

Deep diagnostic profile exploration. Answers questions like:

  • "Why is this user in segment X?"
  • "Why isn't this user in segment Y?"
  • "What happened to this user?" (data lineage)
  • "What does this user look like?" (full profile + memberships)

Goes beyond basic profile lookup by cross-referencing profile data against segment FilterQL to show exactly which conditions match or fail.

Environment

Requires authenticated API access. See ../references/auth.md for credential resolution.

Inputs

  • Identity field and value (e.g., email, [email protected])
  • Segment name or ID (for membership diagnosis)
  • Or a diagnostic question in natural language

Diagnostic Flows

Flow A: "Why is/isn't this user in segment X?"
Step 1: Look Up the Profile

Fetch the full profile with segment memberships:

curl -s "${LYTICS_API_URL:-https://api.lytics.io}/api/entity/user/${FIELD}/${VALUE}?segments=true&allsegments=true" \
  -H "Authorization: ${LYTICS_API_TOKEN}"

This returns:

  • All profile fields and their values
  • segments -- list of segment names the user belongs to
  • segments_all -- list of all segment IDs

Check immediately: is the target segment in the membership list?

Step 2: Fetch the Segment's FilterQL

Get the segment with its fully resolved FilterQL (all INCLUDE directives inlined):

curl -s "${LYTICS_API_URL:-https://api.lytics.io}/v2/segment/${SEGMENT_ID}?inline=true" \
  -H "Authorization: ${LYTICS_API_TOKEN}"

The ql_resolved field contains the complete filter expression with nested segments expanded.

Step 3: Evaluate Each Condition Against the Profile

Parse the FilterQL into individual conditions and check each one against the profile's actual field values.

For each condition in the FilterQL, report:

If the user IS in the segment:

## Why [email protected] IS in "High Value Customers"

FilterQL: FILTER AND (visit_count >= 5, email_engagement > 0.3, country = "US") FROM user

All conditions PASS:
  visit_count >= 5        PASS  (actual: 12)
  email_engagement > 0.3  PASS  (actual: 0.72)
  country = "US"          PASS  (actual: "US")

If the user is NOT in the segment:

## Why [email protected] is NOT in "High Value Customers"

FilterQL: FILTER AND (visit_count >= 5, email_engagement > 0.3, country = "US") FROM user

Condition results:
  visit_count >= 5        PASS  (actual: 12)
  email_engagement > 0.3  FAIL  (actual: 0.15, required: > 0.3)
  country = "US"          PASS  (actual: "US")

The user fails the email_engagement condition. Their value (0.15) is below
the threshold (0.3). This is the reason they are excluded from the segment.
Step 4: Check Included Segments

If the FilterQL references other segments via INCLUDE, check those memberships too:

Segment "High Value Customers" includes "Email Subscribers":
  Email Subscribers membership: YES

  Combined evaluation:
    INCLUDE Email Subscribers   PASS
    visit_count >= 5            PASS  (actual: 12)
    last_purchase > "now-90d"   FAIL  (actual: 2025-01-15, ~63 days ago -- outside 90d window)
Flow B: "What happened to this user?" (Data Lineage)
Step 1: Fetch Entity with Explain Mode
curl -s "${LYTICS_API_URL:-https://api.lytics.io}/api/entity/user/${FIELD}/${VALUE}?explain=true" \
  -H "Authorization: ${LYTICS_API_TOKEN}"

This returns:

  • entity -- the resolved profile
  • fragments -- array of data fragments showing where each piece of data came from
  • keys -- source references (fragment aliases)
Step 2: Present Data Lineage
## Data Lineage: [email protected]

### Identity Resolution
Linked identities:
  email: [email protected]
  _uid: abc-def-123
  user_id: 98765

### Data Sources (N fragments)
Fragment 1: stream "web_events" (last seen: 2026-03-18)
  -> visit_count, pages_viewed, last_visit, referrer

Fragment 2: stream "salesforce_contacts" (last seen: 2026-03-15)
  -> first_name, last_name, company, phone

Fragment 3: stream "email_events" (last seen: 2026-03-19)
  -> email_engagement, newsletters, last_email_open
Flow C: Full Profile Summary
Step 1: Fetch Profile + Segments
curl -s "${LYTICS_API_URL:-https://api.lytics.io}/api/entity/user/${FIELD}/${VALUE}?segments=true&allsegments=true&meta=true" \
  -H "Authorization: ${LYTICS_API_TOKEN}"
Step 2: Present Structured Summary
## Profile: [email protected]

### Identity
  email: [email protected]
  _uid: abc-def-123

### Key Attributes
  Name: Jane Smith
  Country: US
  Created: 2024-01-15
  Last Active: 2026-03-18
  Visit Count: 12

### Segment Memberships (5 segments)
  - High Value Customers (segment)
  - Email Subscribers (aspect)
  - US Users (aspect)
  - Q1 Campaign (list)
  - Active Last 30 Days (segment)

### NOT in these commonly-checked segments
  [If the user asks about specific segments, show which they're not in and why]

Condition Evaluation

When cross-referencing FilterQL conditions against profile data, handle each operator type:

FilterQL ConditionHow to Check
field = "value"Compare profile's field value to literal
field > NNumeric comparison against profile value
field > "now-Nd"Compare profile's date field to calculated threshold
EXISTS fieldCheck if field exists and has a non-empty value in profile
NOT EXISTS fieldCheck if field is missing or empty
field INTERSECTS ("a", "b")Check if profile's set field contains any listed values
field NOT INTERSECTS ("a")Check if profile's set field contains none of the listed values
field CONTAINS "substr"Check if profile's string field contains the substring
field IN ("a", "b")Check if profile's value is in the list
INCLUDE segment_slugCheck if user is a member of the referenced segment

For each condition, always show:

  • The condition itself
  • PASS or FAIL
  • The actual value from the profile (or "field not present" if missing)
  • For FAIL: what value would be needed to pass

Error Handling

  • Profile not found: Try alternative identity fields, suggest checking spelling. URL-encode values with special characters.
  • Segment not found: List segments with similar names, suggest checking the slug.
  • Complex FilterQL: For deeply nested expressions, evaluate the top-level conditions first, then drill into failing branches.
  • Missing fields: If a profile field referenced in FilterQL doesn't exist on the profile, report it clearly -- this is often the root cause.

Dependencies

  • Composes: entity-lookup skill, segment-manager skill
  • References: ../references/filterql-grammar.md, ../references/auth.md, ../references/api-client.md

Comments

Markdown supported