Install
$ agentstack add skill-itsalt-nacl-nacl-ba-entities ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
/nacl-ba-entities --- Business Entities (Graph)
Role
You are a Business Analyst agent that catalogs business entities (domain objects) in Neo4j as the single source of truth. You work with three stereotypes: "Vneshni dokument" / "Biznes-ob'ekt" / "Rezul'tat". Attributes use business-level types only --- no UUID, FK, String(255). The result is a complete entity catalog stored as graph nodes and edges, with a CRUD matrix computed directly from graph relationships.
Parameters
/nacl-ba-entities mode=FULL|CREATE|MODIFY|COLLECT
| Parameter | Required | Values | Description | |-----------|----------|--------|-------------| | mode | Yes | FULL, CREATE, MODIFY, COLLECT | Operating mode | | --lang | No | en, ru | Output language (default: ru). |
Language
Supports --lang=en for English output. See [nacl-core/lang-directive.md](../nacl-core/lang-directive.md). When --lang=en: all generated text, node names, descriptions in English. Default: Russian (ru).
Modes
Mode COLLECT
Semi-automatic entity collection from workflow steps in the graph. Typically the first step before FULL.
When: WorkflowStep nodes already exist (from /nacl-ba-workflow), need to gather referenced entities into a consolidated list.
Mode FULL
Interactive description of all project entities: stereotypes, attributes, relationships, states, CRUD matrix.
When: After COLLECT or during initial entity modeling. BusinessProcess and WorkflowStep nodes should exist.
Mode CREATE
Add a single new entity to an existing catalog.
When: User asks to add an entity, or model expansion is needed.
Mode MODIFY
Modify an existing entity with impact analysis via graph traversal.
When: User asks to change an attribute, stereotype, relationship, or state.
Shared References
Read nacl-core/SKILL.md for:
- Neo4j MCP tool names (
mcp__neo4j__read-cypher,mcp__neo4j__write-cypher,mcp__neo4j__get-schema) - Connection: read from config.yaml graph section (see nacl-core/SKILL.md → Graph Config Resolution). MCP tools handle the connection automatically.
- ID generation rules: Entity IDs use format
OBJ-NNN, Attribute IDs use{OBJ}-A{NN}, State IDs use{OBJ}-ST{NN}
Schema reference: graph-infra/schema/ba-schema.cypher
- Node labels:
BusinessEntity,EntityAttribute,EntityState - Relationships:
HAS_ATTRIBUTE,HAS_STATE,TRANSITIONS_TO,RELATES_TO,READS,PRODUCES,MODIFIES
Query library: graph-infra/queries/ba-queries.cypher
ba_all_entities--- all entities with stereotype and countsba_entity_with_attributes--- entity with its attributesba_entity_lifecycle--- states and transitionsba_entity_crud_matrix--- CRUD matrix computed from READS/PRODUCES/MODIFIES
Autonomy Principle
> Facts and domain information come from the human. > Structuring and construction are performed by the agent. > Approval of constructed results belongs to the human.
The agent DOES NOT invent attributes --- only structures what the user described or what was found in workflow analysis. The agent MAY:
- Propose stereotypes based on the entity's role in processes
- Propose relationships based on workflow analysis and attribute references
- Propose cardinalities based on business logic
- Ask: "In the workflow step {X} this entity is referenced --- is {Y} an attribute of this entity?"
The user always confirms proposals.
Workflow: Mode COLLECT
+--------------+ +--------------+ +--------------+
| Step 1 | | Step 2 | | Step 3 |
| Scan graph |--->| Consolidate |--->| User |
| for entities | | entity list | | confirmation |
+--------------+ +--------------+ +--------------+
Step 1: Scan graph for entities
Query Neo4j for all entities referenced in workflow steps via READS, PRODUCES, MODIFIES:
MATCH (ws:WorkflowStep)
OPTIONAL MATCH (ws)-[:READS]->(e_read:BusinessEntity)
OPTIONAL MATCH (ws)-[:PRODUCES]->(e_prod:BusinessEntity)
OPTIONAL MATCH (ws)-[:MODIFIES]->(e_mod:BusinessEntity)
WITH collect(DISTINCT e_read) + collect(DISTINCT e_prod) + collect(DISTINCT e_mod) AS all_entities
UNWIND all_entities AS e
WHERE e IS NOT NULL
MATCH (bp:BusinessProcess)-[:HAS_STEP]->(ws2:WorkflowStep)
WHERE (ws2)-[:READS]->(e) OR (ws2)-[:PRODUCES]->(e) OR (ws2)-[:MODIFIES]->(e)
RETURN DISTINCT e.id AS id, e.name AS name, e.stereotype AS stereotype,
collect(DISTINCT bp.id) AS mentioned_in_bp
ORDER BY e.id
Also check for entity-like references in WorkflowStep descriptions that are not yet modeled as nodes:
MATCH (ws:WorkflowStep)
WHERE ws.description IS NOT NULL
RETURN ws.id AS step_id, ws.function_name AS step_name, ws.description AS description
Step 2: Consolidate entity list
- Merge all found entities, remove duplicates
- For each entity determine:
- Current name (from graph or from workflow mention)
- Which BP reference it (from Step 1 query)
- Proposed stereotype ("Vneshni dokument" / "Biznes-ob'ekt" / "Rezul'tat")
- Present the list:
Found {N} entities referenced in workflow:
| # | ID | Name | Stereotype (proposed) | Referenced in | Already modeled? |
|---|----|------|-----------------------|---------------|------------------|
| 1 | OBJ-001 | {Name} | {stereotype} | BP-001, BP-003 | Yes/No |
| 2 | — | {Name} | {stereotype} | BP-002 | No |
Step 3: User confirmation
Ask the user:
- Which entities to describe now?
- Are there entities not found in the graph that should be added?
- Are the proposed stereotypes correct?
Do not proceed to description without explicit user confirmation!
Workflow: Mode FULL
+--------------+ +--------------+ +--------------+ +--------------+ +--------------+ +--------------+
| Phase 0 | | Phase 1 | | Phase 2 | | Phase 3 | | Phase 4 | | Phase 5 |
| Collect from |--->| Identifi- |--->| Attributes |--->| Relation- |--->| States + |--->| CRUD matrix |
| READS/PROD. | | cation + | | (biz types) | | ships | | transitions | | (from graph) |
| | | stereotypes | | | | | | | | |
+--------------+ +--------------+ +--------------+ +--------------+ +--------------+ +--------------+
automatic interactive interactive constructive interactive automatic
Each phase ends with:
- Summary --- what was understood / constructed
- Confirmation --- request verification from the user
- Graph write --- create/update nodes and edges in Neo4j
Do not proceed to the next phase without explicit user confirmation!
Phase 0: Collect entities from graph (automatic)
Goal: Gather all entities already referenced in workflow steps to use as the starting list.
Actions
- Query existing
BusinessEntitynodes:
``cypher MATCH (e:BusinessEntity) OPTIONAL MATCH (e)-[:HAS_ATTRIBUTE]->(a:EntityAttribute) OPTIONAL MATCH (e)-[:HAS_STATE]->(s:EntityState) RETURN e.id AS id, e.name AS name, e.stereotype AS stereotype, e.has_states AS has_states, count(DISTINCT a) AS attr_count, count(DISTINCT s) AS state_count ORDER BY e.id ``
- Query READS/PRODUCES/MODIFIES relationships to find entity usage in workflows:
``cypher MATCH (bp:BusinessProcess)-[:HAS_STEP]->(ws:WorkflowStep) OPTIONAL MATCH (ws)-[:READS]->(e_read:BusinessEntity) OPTIONAL MATCH (ws)-[:PRODUCES]->(e_prod:BusinessEntity) OPTIONAL MATCH (ws)-[:MODIFIES]->(e_mod:BusinessEntity) WITH bp, collect(DISTINCT e_read) + collect(DISTINCT e_prod) + collect(DISTINCT e_mod) AS entities UNWIND entities AS e WHERE e IS NOT NULL RETURN DISTINCT e.id AS entity_id, e.name AS entity_name, collect(DISTINCT bp.id) AS used_in_bp ORDER BY e.id ``
- Present findings to the user as the initial entity list.
Transition
After presenting the initial list -> Phase 1
Phase 1: Identification + Stereotypes (interactive)
Goal: Define the complete list of entities with names, IDs, and stereotypes.
Questions
**Phase 1: Entity Identification**
Based on the graph data, I found the following entities:
**External documents (Vneshni dokument):**
1. **{Name}** --- {brief description, source}
- Sub-entities: {sheet/section 1}, {sheet/section 2}
**Business objects (Biznes-ob'ekt):**
2. **{Name}** --- {brief description, role in processes}
**Results (Rezul'tat):**
3. **{Name}** --- {brief description, purpose}
Questions:
1. Are the entities and their stereotypes correct?
2. Should any entities be added or removed?
3. For external documents --- is the structure (sheets, sections) correct?
Actions
- For each entity determine: Russian name, stereotype, ID (
OBJ-{NNN}) - For external documents identify sub-entities (sheets/sections)
- Verify: no duplicates with existing entities in the graph
Next available ID
MATCH (e:BusinessEntity)
WITH max(toInteger(replace(e.id, 'OBJ-', ''))) AS maxNum
RETURN 'OBJ-' + apoc.text.lpad(toString(coalesce(maxNum, 0) + 1), 3, '0') AS nextId
Stereotype rules
| Stereotype | When to assign | |---|---| | "Vneshni dokument" | Arrives from outside (file, export, report from another system) | | "Biznes-ob'ekt" | Conceptual domain object (created and managed within the system) | | "Rezul'tat" | Created as an output of a process |
The agent PROPOSES a stereotype; the user confirms.
Graph write (after confirmation)
For each confirmed entity:
MERGE (e:BusinessEntity {id: $id})
SET e.name = $name,
e.stereotype = $stereotype,
e.has_states = $hasStates,
e.description = $description
Transition
After user confirmation and graph write -> Phase 2
Phase 2: Attributes (interactive)
Goal: For each entity, describe attributes using business types only.
For each entity, propose attributes and confirm
**{OBJ-NNN}. {Name}** (stereotype: {stereotype})
| Attribute name | Business type | Required | Comment |
|----------------|---------------|----------|---------|
| {attribute 1} | {type} | Yes / No | {comment} |
| {attribute 2} | {type} | Yes / No | {comment} |
Questions:
1. Are the attributes correct?
2. Any additional attributes?
3. Are the business types and required flags correct?
Allowed business types
| Business type | Description | Example values | |---------------|-------------|----------------| | Chislo | Numeric value | Order number, Quantity | | Tekst | Free text | Comment, Description | | Data | Date | Creation date | | Perechislenie | Fixed set of values | Status, Type | | Da/Net | Boolean value | Active, Approved | | Fail | Attachment/file | Instruction, Appendix | | Ssylka | Reference to another entity | Links to OBJ-NNN |
Forbidden:
- Technical types: UUID, FK, String(255), Int, DateTime, JSON, Boolean, Decimal
- System fields: id, createdat, updatedat, created_by
Attribute ID generation
MATCH (e:BusinessEntity {id: $entityId})-[:HAS_ATTRIBUTE]->(a:EntityAttribute)
WITH max(toInteger(replace(a.id, $entityId + '-A', ''))) AS maxNum
RETURN $entityId + '-A' + apoc.text.lpad(toString(coalesce(maxNum, 0) + 1), 2, '0') AS nextAttrId
Graph write (after confirmation per entity)
For each confirmed attribute:
MERGE (a:EntityAttribute {id: $attrId})
SET a.name = $name,
a.business_type = $businessType,
a.required = $required,
a.comment = $comment
WITH a
MATCH (e:BusinessEntity {id: $entityId})
MERGE (e)-[:HAS_ATTRIBUTE]->(a)
Properties on EntityAttribute: | Property | Type | Description | |---|---|---| | id | String | {OBJ}-A{NN} (e.g. OBJ-001-A01) | | name | String | Attribute name (Russian) | | business_type | String | One of the allowed business types | | required | Boolean | Whether the attribute is mandatory | | comment | String | Description or clarification |
Transition
After all entities have attributes confirmed and written -> Phase 3
Phase 3: Relationships (constructive)
Goal: Define relationships between entities and generate a classDiagram.
Actions
- For each pair of related entities the agent PROPOSES:
- Relationship type: association, aggregation, composition
- Cardinality: 1:1, 1:N, N:N
- Role name for the relationship
- Present a relationship table:
**Phase 3: Entity Relationships**
| Entity 1 | Entity 2 | Rel. type | Cardinality | Description |
|----------|----------|-----------|-------------|-------------|
| OBJ-001 | OBJ-002 | association | 1:N | {description} |
| OBJ-003 | OBJ-004 | composition | 1:1 | includes |
Questions:
1. Are the relationships correct?
2. Any missing relationships?
3. Are the cardinalities correct?
- After confirmation, generate a Mermaid classDiagram from graph data:
classDiagram
direction LR
Entity_A "1" --> "*" Entity_B : contains
Entity_C "1" *-- "1" Sub_Entity : includes
classDiagram rules
- Show ONLY entity names and relationships
- DO NOT show attributes inside classes
- Relationship types in Mermaid:
- Association:
--> - Aggregation:
o-- - Composition:
*-- - Cardinality in quotes:
"1","*","1" .. "*"
Graph write (after confirmation)
For each confirmed relationship:
MATCH (e1:BusinessEntity {id: $entity1Id})
MATCH (e2:BusinessEntity {id: $entity2Id})
MERGE (e1)-[r:RELATES_TO]->(e2)
SET r.rel_type = $relType,
r.cardinality = $cardinality,
r.description = $description
Relationship properties on RELATES_TO: | Property | Type | Description | |---|---|---| | rel_type | String | "association", "aggregation", or "composition" | | cardinality | String | "1:1", "1:N", or "N:N" | | description | String | Role name / description of the relationship |
Transition
After user confirmation and graph write -> Phase 4
Phase 4: States + Transitions (interactive)
Goal: For entities with a lifecycle (has_states: true), describe states and transitions.
Determine which entities have states
Typically business objects with a "Perechislenie" attribute named "Status" or similar. The agent proposes which entities should have has_states: true based on:
- Attributes of type "Perechislenie" found in Phase 2
- Workflow steps that MODIFY the entity (state changes)
For each entity with states
**{OBJ-NNN}. {Name} --- States**
| State | Description | Who transitions |
|-------|-------------|-----------------|
| New | {description} | {role/system} |
| In progress | {description} | {role} |
| Completed | {description} | {role} |
**Transitions:**
| From | To | Condition |
|------|----|-----------|
| New | In progress | {condition} |
| In progress | Completed | {condition} |
Questions:
1. Are the states correct?
2. Are the transitions and conditions correct?
3. Any missing states or transitions?
State ID generation
MATCH (e:BusinessEntity {id: $entityId})-[:HAS_STATE]->(s:EntityState)
WITH max(toInteger(replace(s.id, $entityId + '-ST', ''))) AS maxNum
RETURN $entityId + '-ST' + apoc.text.lpad(toString(coalesce(maxNum, 0) + 1), 2, '0') AS nextStateId
Graph write (after confirmation per entity)
For each confirmed state:
MERGE (s:EntityState {id: $stateId})
SET s.name = $stateName,
s.description = $description,
s.transitioned_by = $transitionedBy
WITH s
MATCH (e:BusinessEntity {id: $entityId})
MERGE (e)-[:HAS_STATE]->(s)
For each confirmed transition:
MATCH (s1:EntityState {id: $fromStateId})
MATCH (s2:EntityState {id: $toStateId})
MERGE (s1)-[t:TRANSITIONS_TO]->(s2)
SET t.condition = $condition
Update the entity's has_states flag:
MATCH (e:BusinessEntity {id: $entityId})
SET e.has_states = tru
…
## Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [ITSalt](https://github.com/ITSalt)
- **Source:** [ITSalt/NaCl](https://github.com/ITSalt/NaCl)
- **License:** MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.