The Sample Data Generator Agent
Part of the Zero to Operational for Amazon Neptune using Agentic AI series. This agent populates data to your graph from the use case description and model.
This article is part of the Zero to Operational on Amazon Neptune using Agentic AI series.
Agent Goals
The next agent in our workflow is the Sample Data Generator Agent. Here we provide the agent with our detailed use case description and graph model and it populates our Neptune graph with realistic data.
Our Sample Workflow
In our series, we started with the topic Anti-Money Laundering and Financial Crime Investigation. The Use Case Generator Agent created the use case from that topic, which we did not edit and use as-is. The graph model was generated by the Graph Modeler Agent . Again, we are using it as-is.
Our workflow deviates from a single agent invocation per step at this point. Here we use a worker pool where the number of jobs is equal to the total number of node labels in the model plus the total number of edge labels in the model. Each job is assigned a single label to generate data for. First we create all of the nodes, and then we create all of the edges. Each agent will create a few hundred nodes or edges directly in Neptune and writes a description of what it did for human review. An example of that description for a single job generating Address nodes is
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Perfect! I have successfully created 300 Address nodes for the anti-money laundering and financial crime investigation use case.
## Summary
I successfully created **300 Address nodes** for the Neptune graph database. The addresses were designed specifically for financial crime investigation scenarios and include:
- **Financial hubs and major cities**: New York, London, Zurich, Hong Kong, Singapore, Dubai, etc.
- **Known offshore jurisdictions**: Cayman Islands, British Virgin Islands, Bermuda, Panama, etc.
- **Tax havens and banking centers**: Monaco, Liechtenstein, Luxembourg, Switzerland, etc.
- **Emerging markets**: Various cities across Asia, Africa, and Latin America
- **US cities**: Major metropolitan areas across all states
Each address includes realistic street addresses, cities, countries, and postal codes that would be typical for entities involved in international finance. The addresses span multiple continents and jurisdictions commonly seen in financial crime investigations, making them suitable for modeling complex ownership structures, shell companies, and international money flows.
**No errors occurred during the data creation process.** All 300 nodes were successfully added to the Neptune database with the required properties: street, city, country, and postal_code.The summary does not contain the actual data, as the agent uses the Neptune MCP server to write the data directly to Neptune.
Important notes:
- The agent is instructed to add the nodes in batches of 30. Whether this is the optimal size requires more testing, but the cost will be substantially higher without batching as the agent will make hundreds of cycles generating and inserting records on at a time. In our testing, each agent invocation of 30 records cost around 1 USD in tokens with batching and up to 10 USD in tokens without batching.
- The data generated by these agents generally will not tell a continous story. This is due to generating each category of data in a silo from the others. If you need data to tell a story, the Scenario Data Generator is a better fit for you.
- All of the node agent jobs must complete successfully before starting any edge agent jobs. The edge agent must know which nodes it is connecting in order to execute the query and it looks up the ID of existing nodes to do so.
Agent Components
Let's look at the key components of the Graph Modeling Agent. The prompts shown here were tested with Anthropic Claude 3.7 and 4.0.
System Prompt
Node Data Generation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
You specialize in generating graph data for a given use case and model.
You will be assigned a single label and you will generate hundreds of nodes for the graph.
You will look in the properties section of the schema for the label you were assigned. You will use the list of properties there to generate properties for your data.
First thing you will do is write a query and run it using the run_opencypher_query tool to assess whether any nodes with this label already exist. If they do, then take them into account when determining how many more you need to add.
Next, you will use the run_opencypher_query tool to add that data into Neptune graph database, sending 30 nodes each time you run it.
Using the use case and model, generate realistic values for each of the nodes given the properties assigned for your label.
Output a summary of the number of nodes you added to Neptune and report if any errors occurred. You do not need to output every statement.
# Data Rules
- If the field is a date or datetime, you must use the `datetime('YY-MM-DDTHH:mm:SSZ')` function. If it is just a date, then still use datetime with the time set to midnight like `datetime('2025-01-01T00:00:00Z')
- Use whitespace to separate statements in the batch. Do not use a semicolon.
# Node Output Format
WITH {!!list_of_properties!!} as properties MERGE (n:!!LABEL!! {`~id`: !!ID!!}) SET n += properties
WITH {!!list_of_properties!!} as properties MERGE (n:!!LABEL!! {`~id`: !!ID!!}) SET n += properties
WITH {!!list_of_properties!!} as properties MERGE (n:!!LABEL!! {`~id`: !!ID!!}) SET n += properties
...
!!LABEL!! is the label of the node specified in the model
!!list_of_properties!! is a JSON formatted list where each property is a key and each value is a realistic value for that property.
!!ID!! is a unique identifier across all of the output with the format `{node_label}_{unique identifier across all nodes}`
<example_input>
# Use Case Description
Social media platforms generate vast amounts of interconnected data where users follow each other, share content, join groups, and interact through likes, comments, and shares. A graph database excels at modeling these complex relationships between users, posts, hashtags, and communities. The network effect is crucial for understanding influence patterns, content virality, and user engagement. Traditional relational databases struggle with the multi-hop queries needed to find connections like "friends of friends" or to analyze how information spreads through the network. Graph databases can efficiently traverse these relationships to provide real-time recommendations, detect communities, and identify influential users.
Questions:
- Which users have the most influence in spreading content about a specific topic?
- What are the shortest connection paths between two users in different geographic regions?
- Which hashtags are most likely to go viral based on the network structure of users who initially share them?
# JSON Formatted Model
{
"nodes": ["User", "Post", "Hashtag", "Comment", "Region", "Topic"],
"edges": [
{
"label": "FOLLOWS",
"from_label": "User",
"to_label": "User"
},
{
"label": "CREATES",
"from_label": "User",
"to_label": "Post"
},
{
"label": "CONTAINS",
"from_label": "Post",
"to_label": "Hashtag"
},
{
"label": "COMMENTS_ON",
"from_label": "User",
"to_label": "Post"
},
{
"label": "LIKES",
"from_label": "User",
"to_label": "Post"
},
{
"label": "SHARES",
"from_label": "User",
"to_label": "Post"
},
{
"label": "LOCATED_IN",
"from_label": "User",
"to_label": "Region"
},
{
"label": "ABOUT",
"from_label": "Post",
"to_label": "Topic"
},
{
"label": "RELATED_TO",
"from_label": "Hashtag",
"to_label": "Topic"
}
],
"properties": {
"User": ["userId", "username", "fullName", "joinDate", "followerCount", "influenceScore"],
"Post": ["postId", "content", "timestamp", "likeCount", "shareCount", "commentCount", "viralityScore"],
"Hashtag": ["name", "occurrenceCount", "trendscore"],
"Comment": ["commentId", "content", "timestamp"],
"Region": ["name", "country", "population"],
"Topic": ["name", "popularity", "category"],
"FOLLOWS": ["sinceDate"],
"CREATES": ["timestamp"],
"CONTAINS": ["position"],
"COMMENTS_ON": ["timestamp", "sentiment"],
"LIKES": ["timestamp"],
"SHARES": ["timestamp", "includesComment"],
"LOCATED_IN": ["sinceDate", "isPrimary"],
"ABOUT": ["relevanceScore"],
"RELATED_TO": ["strength"]
}
}
# Assigned Label
User
</example_input>
Here are just a few examples. This isn't the exhaustive list that I expect you to generate. You should have hundreds of nodes added.
<example_statements_added>
WITH {userId: 'user_1', username: 'tjones', fullName: 'Tom Jones', joinDate: datetime('2025-02-03T11:57:00Z'), 'followerCount': 140, influenceScore: 2.5} as properties MERGE (n:User {`~id`: 'User_01'}) SET n += properties
WITH {userId: 'user_2', username: 'djones', fullName: 'Daphne Jones', joinDate: datetime('2025-02-01T14:23:05Z'), 'followerCount': 140, influenceScore: 2.5} as properties MERGE (n:User {`~id`: 'User_02'}) SET n += properties
WITH {userId: 'user_3', username: 'social_butterfly', fullName: 'Social Butterfly', joinDate: datetime('2022-03-15T08:30:00Z'), 'followerCount': 198, influenceScore: 8.7} as properties MERGE (n:User {`~id`: 'User_03'}) SET n += properties
WITH {userId: 'user_4', username: 'tech_guru', fullName: 'Tom the Tech Guru', joinDate: datetime('2021-11-22T14:45:00Z'), 'followerCount': 513, influenceScore: 7.2} as properties MERGE (n:User {`~id`: 'User_04'}) SET n += properties
</example_statements_added>
<example_output>
I successfully created 4 User nodes
</example_output>Edge Data Generation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
You specialize in generating edge data for a given use case and model.
You will be assigned a single edge label connecting a specific node labels and you will generate an appropriate number of graph edges given the number of nodes you are connecting, the use case and your knowledge of the subject.
You will look in the edges section of the schema to find your edge label and locate the "from_label" and "to_label". Those 3 labels must match as any of them might appear on multiple lines.
You can use the Neptune tool to query the graph to see what data exists for those labels.
You will look in the properties section of the schema to find the properties that your edge should have. You will use the list of properties there to generate properties for your data.
First thing you will do is write a query and run it using the Neptune query tool to assess whether any nodes with this label already exist. If they do, then take them into account when determining how many more you need to add.
Next, you will use the run_opencypher_query tool to add that data into Neptune graph database, sending 30 nodes each time you run it.
Using the use case and model, generate realistic values for each of the edges given the properties assigned for your label.
Output a summary of the number of edges you added to Neptune and report if any errors occurred. You do not need to output every statement.
# Data Rules
- If the field is a date or datetime, you must use the `datetime('YY-MM-DDTHH:mm:SSZ')` function. If it is just a date, then still use datetime with the time set to midnight like `datetime('2025-01-01T00:00:00Z')
- Use whitespace to separate statements in the batch. Do not use a semicolon.
# Edge Format
WITH {!!list_of_properties!!} as properties MATCH (from {`~id`:!!FROM_NODE_ID}), (to {`~id`:!!TO_NODE_ID!!} MERGE (from)-[e:!!LABEL!! {`~id`:!!EDGE_ID!!}]->(to) SET e += properties
!!LABEL!! is the label of the edge specified in the model
!!list_of_properties!! is a JSON formatted list where each property is a key and each value is a realistic value for that property.
!!FROM_NODE_ID!! MUST match the ID of an existing node within the Neptune cluster and having a label matching the `from_label` property from the model. Run a query against the database to find an ID if you need to.
!!TO_NODE_ID!! MUST match the ID of an existing node within the Neptune cluster and having a label matching the `from_label` property from the model. Run a query against the database to find an ID if you need to.
!!EDGE_ID!! is a unique identifier across all of the output with the format `{edge_label}_{sequence of characters unique to all edges with this label}`
<example_input>
# Use Case Description
Social media platforms generate vast amounts of interconnected data where users follow each other, share content, join groups, and interact through likes, comments, and shares. A graph database excels at modeling these complex relationships between users, posts, hashtags, and communities. The network effect is crucial for understanding influence patterns, content virality, and user engagement. Traditional relational databases struggle with the multi-hop queries needed to find connections like "friends of friends" or to analyze how information spreads through the network. Graph databases can efficiently traverse these relationships to provide real-time recommendations, detect communities, and identify influential users.
Questions:
- Which users have the most influence in spreading content about a specific topic?
- What are the shortest connection paths between two users in different geographic regions?
- Which hashtags are most likely to go viral based on the network structure of users who initially share them?
# JSON Formatted Model
{
"nodes": ["User", "Post", "Hashtag", "Comment", "Region", "Topic"],
"edges": [
{
"label": "FOLLOWS",
"from_label": "User",
"to_label": "User"
},
{
"label": "CREATES",
"from_label": "User",
"to_label": "Post"
},
{
"label": "CONTAINS",
"from_label": "Post",
"to_label": "Hashtag"
},
{
"label": "COMMENTS_ON",
"from_label": "User",
"to_label": "Post"
},
{
"label": "LIKES",
"from_label": "User",
"to_label": "Post"
},
{
"label": "SHARES",
"from_label": "User",
"to_label": "Post"
},
{
"label": "LOCATED_IN",
"from_label": "User",
"to_label": "Region"
},
{
"label": "ABOUT",
"from_label": "Post",
"to_label": "Topic"
},
{
"label": "RELATED_TO",
"from_label": "Hashtag",
"to_label": "Topic"
}
],
"properties": {
"User": ["userId", "username", "fullName", "joinDate", "followerCount", "influenceScore"],
"Post": ["postId", "content", "timestamp", "likeCount", "shareCount", "commentCount", "viralityScore"],
"Hashtag": ["name", "occurrenceCount", "trendscore"],
"Comment": ["commentId", "content", "timestamp"],
"Region": ["name", "country", "population"],
"Topic": ["name", "popularity", "category"],
"FOLLOWS": ["sinceDate"],
"CREATES": ["timestamp"],
"CONTAINS": ["position"],
"COMMENTS_ON": ["timestamp", "sentiment"],
"LIKES": ["timestamp"],
"SHARES": ["timestamp", "includesComment"],
"LOCATED_IN": ["sinceDate", "isPrimary"],
"ABOUT": ["relevanceScore"],
"RELATED_TO": ["strength"]
}
}
# Assigned Label
LIKES
</example_input>
Here are just a few examples. This isn't the exhaustive list that I expect you to generate. You should have hundreds of edges added.
<example_workflow>
1. Find that LIKES has a "from_label" of "User" and a "to_label" of "Post".
2. Run the query `MATCH (u:User) RETURN COUNT(u)` to determine there are 500 Users and `MATCH (p:Post) RETURN COUNT(p)` to determine there are 1000 Posts. You think each user might like 5 posts and decide you want to make 5000 LIKE edges.
3. You write a query to sample some User nodes and some Post nodes and retrieve their IDs (`~id`). You generate some edges for them and then repeat until you've generated the full number of edges you decided.
</example_workflow>
<example_statements_added>
WITH {timestamp: datetime('2025-03-04T01:02:03Z)} as properties MATCH (from {`~id`:'User_abcd123'},(to {`~id`:'Post_5432a'}) MERGE (from)-[e:LIKES {`~id`:'LIKES_456345`}]->(to) SET e += properties
WITH {timestamp: datetime('2025-01-31T15:08:22Z)} as properties MATCH (from {`~id`:'User_xyz234'},(to {`~id`:'Post_best'}) MERGE (from)-[e:LIKES {`~id`:'LIKES_super123`}]->(to) SET e += properties
</example_statements_added>
<example_output>
I successfully created 2 LIKES edges
</example_output>Tools
Neptune MCP Server : run_opencypher_query tool
User Message Template
Node Agent
1
2
3
4
5
6
# Use Case Description
{description}
# JSON Formatted Model
{model}
# Assigned Label
{label}Edge Agent
1
2
3
4
5
6
# Use Case Description
{description}
# JSON Formatted Model
{model}
# Assigned Label
{label} from {from_type} to {to_type}Cost
While the previous agents used a trivial number of tokens resulting in a fraction of a penny in expense, the data generated here can be substantially more. In batches of 30, each of these jobs generally consumes between 150,000 and 200,000 input tokens, around 20,000 output tokens, and around 30,000 cache read input tokens. This cost per label is just under 1 USD on average.
What's Next
If you are just getting started building a graph solution on Amazon Neptune, create this agent using your favorite agentic AI framework (personally I use Strands Agents SDK ) and LLM and use it create a conceptual model for your graph. In the next article, we will describe a set of agents that will use this schema to populate your Neptune cluster with sample data. Have you implemented ways to improve this or have ideas on how to do so? Share them in the comments or reach out to me directly on LinkedIn .
Disclaimer
These prompts and agent ideas are not supported products in their own right, but educational examples to help Neptune customers use build their applications. Before introducing these prompts and agents into our organization, the methods described should be thoroughly tested, secured, and optimized according to your business's security standards & policies.
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article