Agent skill

Flowsint Enricher Builder

by reconurge in reconurge/flowsint

Guides building Flowsint enrichers and types: where definitions live, how the base class and vault work, and when a new type is warranted.

Apache-2.0Auto-check passedDevelopment

Install Flowsint Enricher Builder

skills CLI
$ npx skills add reconurge/flowsint --skill flowsint-enricher-builder -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install reconurge/flowsint flowsint-enricher-builder --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/reconurge/flowsint.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/flowsint-enricher-builder .claude/skills/flowsint-enricher-builder && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
flowsint-enricher-builder
GitHub stars
9.6k
Token cost
~2.6k tokens
SKILL.md length
1,015 words
Files
1
Skills in repo
1
Repo updated
First seen
Licence
Apache-2.0

At a glance

Guides building Flowsint enrichers and types: where definitions live, how the base class and vault work, and when a new type is warranted.

  • Works in 4 steps: List the entities involved — input data,… → For each, check… → Decide → …
  • Adding a new enricher to Flowsint
  • SKILL.md covers Authoritative source paths, The first question: new type…, Anatomy of an enricher and Params and secrets, plus 6 more sections
  • Calls poetry and make

What it does

This skill has the agent build enrichers and entity types for Flowsint by reading the source instead of relying on memory. It lists the authoritative paths: type definitions and their registry, the enricher base class and registry, existing enrichers as templates, the UI category mapping, the vault and logger interfaces, external tool wrappers under tools/, and the developer docs for types, enrichers and the catalog.

Its first question for any new enricher is whether to reuse a type, extend one or create a new one. It reuses a type that covers all required fields, extends it when one or two optional fields are missing, and creates a new type when the entity is distinct, with a different primary key, label meaning or graph role. It warns against forcing data into the wrong type, for example putting risk scores into Domain metadata when a RiskProfile type exists.

It also covers wiring in an external API or tool, resolving vault secrets and params, debugging why types or enrichers are not discovered, and designing a pivot from one entity to another.

When your agent uses it

  • Adding a new enricher to Flowsint
  • Creating a new Flowsint type for a distinct entity
  • Wiring an external API or command-line tool into Flowsint
  • Debugging why a type or enricher is not discovered

Example prompts

  • “Add a Flowsint enricher that takes a domain and returns its WHOIS registrant details.”
  • “Should this breach lookup return a new type or reuse an existing one? Check the types first.”
  • “Wire the subfinder tool into a new enricher that pivots from a domain to its subdomains.”
  • “My new enricher does not show up in the UI. Find out why discovery is skipping it.”

Requirements

  • A checkout of the Flowsint repository
  • Python

Workflow steps

4 steps, taken from the first numbered list in SKILL.md.

  1. List the entities involved — input data, output data, intermediate fields you'll attach.
  2. For each, check flowsint-types/src/flowsint_types/ — open the closest candidate file and read its fields.
  3. Decide
  4. Never cram data into a wrong type. If a "Domain" enricher returns risk scores, a RiskProfile exists — don't stuff scores into Domain…

What it can do on your machine

Read from SKILL.md and the folder at commit 4c05849. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • poetry
    • make

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Flowsint Enricher Builder loads about 2.6k tokens when it runs. Until then it costs about 120 tokens; SKILL.md has 1,015 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~120
When it runs · the whole SKILL.md, loaded when a task matches
~2.6k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from reconurge/flowsint at commit 4c05849, republished under its Apache-2.0 licence (© reconurge). 1,015 words, ~2,632 tokens.

Download SKILL.mdSave it as .claude/skills/flowsint-enricher-builder/SKILL.md (or your agent's skills folder).
name
flowsint-enricher-builder
description
Expert guidance for building Flowsint enrichers and their supporting types. Use when the user wants to add a new enricher, create a new Flowsint type, wire a new external API/tool into Flowsint, debug type/enricher discovery, or design a pivot from entity A to entity B. Knows where types live, how the enricher base class works, how vault secrets and params resolve, and when to recommend creating a new type instead of forcing data into an existing one.

Flowsint Enricher Builder

You build enrichers and types for Flowsint. You do not memorize the catalog — you know where to look and how the pieces fit. Always read source before generating code: type definitions and existing enrichers are the ground truth.

Authoritative source paths

Read these first. Never assume signatures or fields — open the file.

WhatPath
Type definitionsflowsint-types/src/flowsint_types/<name>.py
Type registry + decoratorflowsint-types/src/flowsint_types/registry.py
Type package exportsflowsint-types/src/flowsint_types/__init__.py
Enricher base classflowsint-core/src/flowsint_core/core/enricher_base.py
Enricher registry + decoratorflowsint-enrichers/src/flowsint_enrichers/registry.py
Existing enrichers (templates)flowsint-enrichers/src/flowsint_enrichers/<input_type>/to_<output>.py
UI category mappingflowsint-core/src/flowsint_core/core/services/type_registry_service.py (_get_category_definitions)
Vault interfaceflowsint-core/src/flowsint_core/core/vault.py
Logger interfaceflowsint-core/src/flowsint_core/core/logger.py
Tools (external CLI/API wrappers)tools/ (top-level), e.g. tools.network.subfinder.SubfinderTool
Doc — types tutorialdocs/developers/managing-types.mdx
Doc — enrichers tutorialdocs/developers/managing-enrichers.mdx
Doc — enricher catalogdocs/sources/available-enrichers.mdx

The first question: new type or reuse?

When the user describes a enricher, decide before writing code:

  1. List the entities involved — input data, output data, intermediate fields you'll attach.
  2. For each, check flowsint-types/src/flowsint_types/ — open the closest candidate file and read its fields.
  3. Decide:
    • Reuse if existing type covers all required fields (extras allowed — ConfigDict.extra = "allow").
    • Extend an existing type if 1–2 fields are missing — propose adding optional fields to the existing model.
    • Create new type if the entity is conceptually distinct (different primary key, different label semantics, different graph role).
  4. Never cram data into a wrong type. If a "Domain" enricher returns risk scores, a RiskProfile exists — don't stuff scores into Domain metadata. If nothing fits, propose a new type and tell the user why.

Surface the decision to the user before generating code: list candidate types you found, what's missing, and your recommendation.

Anatomy of an enricher

Minimum surface (read enricher_base.py for the full contract):

python
from typing import List
from flowsint_core.core.enricher_base import Enricher
from flowsint_core.core.logger import Logger
from flowsint_enrichers.registry import flowsint_enricher
from flowsint_types import Domain, Ip  # or whatever types


@flowsint_enricher
class MyEnricher(Enricher):
    """[Source name] One-line purpose."""

    InputType = Domain  # base type, not List[Domain]
    OutputType = Ip

    @classmethod
    def name(cls) -> str:
        return "domain_to_ip"  # snake_case, unique

    @classmethod
    def category(cls) -> str:
        return "Domain"  # see note on casing below

    @classmethod
    def key(cls) -> str:
        return "domain"  # primary field of InputType

    @classmethod
    def get_params_schema(cls):  # optional, only if params needed
        return [...]

    async def scan(self, data: List[InputType]) -> List[OutputType]: ...

    def postprocess(self, results, input_data):
        for src, dst in zip(input_data, results):
            self.create_node(src)
            self.create_node(dst)
            self.create_relationship(src, dst, "RESOLVES_TO")
        return results


InputType = MyEnricher.InputType
OutputType = MyEnricher.OutputType

File location: flowsint-enrichers/src/flowsint_enrichers/<input_type>/to_<target>.py. The directory matches the input type's lowercase name. If no directory exists for your input type, create it (no __init__.py needed — auto-discovery walks the tree).

Registration: the @flowsint_enricher decorator does it. Do not edit any registry.py. API restart picks up new files via load_all_enrichers().

Params and secrets

Defined via get_params_schema() classmethod. Each entry is a dict:

FieldRequiredNotes
nameyesParam key; for vaultSecret, also the default vault key name
typeyesOne of string, number, select, url, vaultSecret
descriptionyesShown in UI
requirednoDefaults to false
defaultnoDefault value
optionsfor selectList of {"label": ..., "value": ...}

Read params inside scan():

python
mode = self.params.get("mode", "passive")
api_key = self.get_secret("MY_API_KEY")  # vault-resolved during async_init

Vault resolution flow (see Enricher.resolve_params in enricher_base.py):

  1. If user passed a vault ID in params → vault looked up by that ID.
  2. Else → vault looked up by the param name (e.g. MY_API_KEY).
  3. If required: true and nothing found → Exception("Required vault secret 'MY_API_KEY' is missing...").

Never hardcode keys. Always declare a vaultSecret param. Document the expected vault key name in the docstring.

Graph operations (postprocess)

create_node(obj) and create_relationship(from_obj, to_obj, rel_label="IS_RELATED_TO") take Pydantic objects directly. Don't manually construct node dicts — pass the typed instance.

Relationship label convention: UPPER_SNAKE_CASE verb phrase (HAS_DOMAIN, RESOLVES_TO, FOUND_IN_BREACH). Be consistent with existing enrichers — grep before inventing a new label.

self.log_graph_message("...") for graph-related progress logs. Logger.info / error / warn(self.sketch_id, {"message": "..."}) for general logs.

Creating a new type — checklist

When you decide a new type is warranted:

  1. File: flowsint-types/src/flowsint_types/<snake_case>.py.
  2. Class: PascalCase, inherit from FlowsintType, decorate with @flowsint_type.
  3. Exactly one primary field: Field(..., json_schema_extra={"primary": True}). Must uniquely identify the entity (used as Neo4j MERGE key).
  4. compute_label: @model_validator(mode='after'), sets self.nodeLabel, returns self. Handle None for optional fields.
  5. Export in __init__.py: add import + entry in __all__.
  6. Category (optional but recommended): add a ("MyType", "primary_field_name", icon) tuple in _get_category_definitions() in type_registry_service.py. Without this, the type works as an enricher I/O but doesn't show in the UI type picker.
  7. Reinstall: cd flowsint-types && poetry install (or make prod from repo root).
  8. Test: write a tests/test_<name>.py covering creation, primary uniqueness, compute_label with full/partial fields.

Full template + patterns: docs/developers/managing-types.mdx.

Show full SKILL.md (395 more words)Show less

Naming conventions (already-established, don't break)

  • Enricher name(): <input>_to_<output> snake_case (e.g. domain_to_ip, email_to_breaches).
  • Enricher file: to_<target>.py under <input_type>/ directory.
  • Class name: descriptive PascalCase (e.g. DomainToIpEnricher, WhoisEnricher).
  • Type class: PascalCase. Type file: snake_case.
  • Relationship label: UPPER_SNAKE_CASE verb.
  • Docstring of enricher class starts with [ToolName/Source] tag — convention used across the codebase (e.g. """[DeHashed] Get breach intelligence ...""").

Known smell: category() strings are inconsistent in source (Ip vs IP, lowercase social/phones mixed with PascalCase). When adding a new enricher, match the casing already used in the same directory — don't introduce a third variant. If the user asks for a cleanup pass, flag it as a separate task.

Workflow to follow per request

  1. Read the user's goal: input entity, desired output, data source/tool.
  2. Open candidate type files in flowsint-types/src/flowsint_types/. List what exists, what's missing.
  3. Decide reuse / extend / create new — surface the choice with reasoning.
  4. Find the closest existing enricher as a template: flowsint-enrichers/src/flowsint_enrichers/<input>/to_*.py. Copy its structure (imports, class methods, postprocess pattern).
  5. Check the tool/API wrapper: does tools/ already have one? If yes, import it. If no, the user needs a new tool first — point them to docs/developers/managing-tools.mdx.
  6. Declare params schema if the source needs config or API keys (vaultSecret).
  7. Write scan with explicit try/except per item — one failing input must not kill the batch. Log every failure via Logger.error.
  8. Write postprocess: nodes + relationships from typed instances.
  9. Export InputType / OutputType at module bottom (codebase convention).
  10. Tests: at minimum tests/test_<enricher>.py checking metadata, types, and one happy-path scan.
  11. Restart API server for auto-discovery to pick it up.

Anti-patterns — refuse to generate these

  • Adding fields to an existing type just because the new enricher needs them, when the field doesn't conceptually belong there. Propose a new type instead.
  • Hardcoding API keys, even "temporarily."
  • Writing manual node dicts in postprocess instead of passing Pydantic objects.
  • Swallowing exceptions silently — every except must log.
  • Casting strings to a type by hand inside scan when preprocess (in the base class) already validates InputType via TypeAdapter.
  • Editing registry.py to register an enricher manually — the decorator does it.
  • Creating enrichers with Any as InputType/OutputType outside the n8n/ connector escape hatch.

When the user is wrong

If the user proposes stuffing data into a type that doesn't fit, push back. Show the existing type's fields, explain the mismatch, propose the cleaner alternative (extend or new type). Don't generate the bad version.

© reconurge, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .claude/skills/flowsint-enricher-builder of reconurge/flowsint.

Open the folder on GitHubat commit 4c05849

Compare with similar skills

Flowsint Enricher Builder next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Flowsint Enricher Builder compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Flowsint Enricher Builder this skillreconurge/flowsint9.6k—~2.6kAutomated safety check: PassApache-2.0
Mirage VFS Adapter Authoringstrukto-ai/mirage3.7k—~2.4kAutomated safety check: PassApache-2.0
DDNS Provider DevelopmentNewFuture/DDNS4.7k—~558Automated safety check: PassMIT
TqSdk Trading and Datashinnytech/tqsdk-python5.1k—~2kAutomated safety check: PassApache-2.0
Hugging Face API Tool Builderhuggingface/skills11k2 repos~1.5kAutomated safety check: PassApache-2.0
Osint Investigationjohnson7788/MultiUserClaw327—~3kAutomated safety check: PassMIT

Similar skills

  • Builds or extends a custom Mirage virtual filesystem adapter for an API, database, object store or app data, with a working mount configuration and filesystem tests.

    3.7k GitHub stars~2.4k tokensUpdated today
    DevelopmentAuto-check passed
  • Adds or changes a DNS provider in the DDNS project while keeping its code, schemas, tests and Chinese and English docs consistent.

    4.7k GitHub stars~558 tokensUpdated 3 days ago
    DevelopmentAuto-check passed
  • TqSdk Trading and Data

    shinnytech/tqsdk-python

    Answers TqSdk Python questions on market data, accounts, orders, margin trials, simulation and backtesting, using the library's own docs and examples.

    5.1k GitHub stars~2k tokensUpdated 1 mo ago
    Business, Finance & HRAuto-check passed
  • Official

    Builds reusable command line scripts that fetch, enrich or process data from the Hugging Face API, aimed at chained, repeated or automated tasks.

    11k GitHub starsUsed in 2 repos~1.5k tokens
    AI & LLM EngineeringAuto-check passed
  • Osint Investigation

    johnson7788/MultiUserClaw

    Public-records OSINT investigation framework — SEC EDGAR filings, USAspending contracts, Senate lobbying, OFAC sanctions, ICIJ offshore leaks, NYC property records (ACRIS), OpenCorporates…

    327 GitHub stars~3k tokensUpdated 1 mo ago
    SecurityAuto-check passed
  • Domain Intel

    Tommy-yw/RunbookHermes

    Passive domain reconnaissance using Python stdlib. An agent skill from Tommy-yw/RunbookHermes.

    546 GitHub starsUsed in 1 repo~1.1k tokens
    SecurityAuto-check passed

Works with

Questions about Flowsint Enricher Builder

What does Flowsint Enricher Builder do?

Guides building Flowsint enrichers and types: where definitions live, how the base class and vault work, and when a new type is warranted. This skill has the agent build enrichers and entity types for Flowsint by reading the source instead of relying on memory. It lists the authoritative paths: type definitions and their registry, the enricher base class and registry, existing enrichers as templates, the UI category mapping, the vault and logger interfaces, external tool wrappers under tools/, and the developer docs for types, enrichers and the catalog.

When should I use Flowsint Enricher Builder?

Flowsint Enricher Builder fits situations like: adding a new enricher to Flowsint; creating a new Flowsint type for a distinct entity; wiring an external API or command-line tool into Flowsint; debugging why a type or enricher is not discovered.

How do I install Flowsint Enricher Builder in Claude Code?

Run `npx skills add reconurge/flowsint --skill flowsint-enricher-builder -a claude-code`. Or copy the skill folder (.claude/skills/flowsint-enricher-builder in reconurge/flowsint) into .claude/skills/flowsint-enricher-builder in your project. Claude Code loads it when a task matches its description.

How do I install Flowsint Enricher Builder in Codex?

Run `npx skills add reconurge/flowsint --skill flowsint-enricher-builder -a codex`. Or copy the skill folder (.claude/skills/flowsint-enricher-builder in reconurge/flowsint) into .agents/skills/flowsint-enricher-builder in your project. Codex loads it when a task matches its description.

Can I use Flowsint Enricher Builder in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add reconurge/flowsint --skill flowsint-enricher-builder -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/flowsint-enricher-builder, .gemini/skills/flowsint-enricher-builder, .github/skills/flowsint-enricher-builder and .opencode/skills/flowsint-enricher-builder in your project.

What does Flowsint Enricher Builder need to run?

Going by SKILL.md and its folder, Flowsint Enricher Builder needs the command-line tools its instructions call (poetry and make). Our summary lists: A checkout of the Flowsint repository; Python.

Does Flowsint Enricher Builder access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Flowsint Enricher Builder safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Flowsint Enricher Builder use?

Flowsint Enricher Builder is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Flowsint Enricher Builder use?

About 2.6k tokens (SKILL.md is roughly 11k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Flowsint Enricher Builder?

Skills that share tags, products or a category with Flowsint Enricher Builder: Mirage VFS Adapter Authoring (strukto-ai/mirage, 3.7k stars), DDNS Provider Development (NewFuture/DDNS, 4.7k stars), TqSdk Trading and Data (shinnytech/tqsdk-python, 5.1k stars) and Hugging Face API Tool Builder (huggingface/skills, 11k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Flowsint Enricher Builder?

reconurge (a GitHub organization) maintains it in reconurge/flowsint, which has 9,590 GitHub stars. The repository was last updated on October 3, 2026.

Source: reconurge/flowsint on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.