{"id":1449,"date":"2026-06-25T08:42:00","date_gmt":"2026-06-25T15:42:00","guid":{"rendered":"https:\/\/www.kenwalger.com\/blog\/?p=1449"},"modified":"2026-04-23T07:58:20","modified_gmt":"2026-04-23T14:58:20","slug":"building-social-graphs-with-ai-agents","status":"publish","type":"post","link":"https:\/\/www.kenwalger.com\/blog\/ai\/building-social-graphs-with-ai-agents\/","title":{"rendered":"Mapping the Social Graph"},"content":{"rendered":"<p>In <a href=\"https:\/\/www.kenwalger.com\/blog\/ai\/engineering-ai-agent-memory-json-ld\">our previous post<\/a>, we built the Knowledge Archive, a durable, atomic vault for historical data. We moved from &#8220;strings to things&#8221; by adopting the Schema.org vocabulary. But even with a vault full of people, the Scribe was still seeing individuals in isolation.<\/p>\n<p>History isn&#8217;t just a list of names; it\u2019s a web of <strong>Relationships<\/strong>. Today, we move from the Archive to the <em>Social Graph<\/em>.<\/p>\n<h2>Beyond the Nuclear Family<\/h2>\n<p>The 1880 Census is a social map. In a single dwelling in Salem, Oregon, you might find a Head of Household, his wife, four children, two boarders (often young laborers), and a live-in servant.<\/p>\n<p>To capture this, the Digital Scribe needs to move beyond simple genealogy. We&#8217;ve engineered a <strong>Relational Linker<\/strong> that recognizes the &#8220;connective tissue&#8221; of a household:<\/p>\n<ul>\n<li><strong>Nuclear Ties:<\/strong> Mapping &#8220;Wife&#8221; and &#8220;Husband&#8221; to <code>schema:spouse<\/code> and &#8220;Son\/Daughter&#8221; to <code>schema:parent<\/code>.<\/li>\n<li><strong>Extended Ties:<\/strong> Mapping &#8220;Boarder,&#8221; &#8220;Servant,&#8221; and &#8220;Cook&#8221; to a <code>memberOfHousehold<\/code> relationship.<\/li>\n<\/ul>\n<p>The scribe uses a specialized &#8216;Idempotent Appender.&#8217; This function is a surgical tool: it checks if a relationship already exists before adding it. If it finds a bare string ID from an older version of the archive, it &#8216;promotes&#8217; it to a structured dictionary, ensuring the archive&#8217;s schema remains perfectly consistent over time.<\/p>\n<pre><code class=\"language-python\"># The Idempotent Relation Appender\ndef _add_to_relation(entity: dict, property_name: str, value: dict) -&gt; bool:\n    target_id = value.get(\"@id\")\n    existing = entity.get(property_name)\n\n    # Promotion logic: Convert bare strings to structured dictionaries\n    if isinstance(existing, str):\n        if existing == target_id: return False\n        entity[property_name] = [{\"@id\": existing}, value]\n        return True\n\n    # ... handles lists and deduplication to prevent redundant data ...\n<\/code><\/pre>\n<pre><code class=\"language-mermaid\">graph LR\n    %% --- Central Entity ---\n    Head[Head of Household]\n\n    %% --- Nuclear Family ---\n    subgraph Nuclear [\"Nuclear Unit\"]\n        Spouse[Spouse: Wife or Husband]\n        Child[Son or Daughter]\n    end\n\n    %% --- Extended Household ---\n    subgraph Extended [\"Extended Household\"]\n        Boarder[Boarder]\n        Servant[Servant]\n    end\n\n    %% --- Relationship Edges ---\n    %% Symmetric Spouse Link\n    Head ---|spouse| Spouse\n    Spouse ---|spouse| Head\n\n    %% Parent\/Child Links\n    Child --&gt;|parent| Head\n    Head -.-&gt;|knows| Child\n\n    %% Extended links\n    Boarder --&gt;|memberOfHousehold| Head\n    Servant --&gt;|memberOfHousehold| Head\n\n    Head -.-&gt;|knows| Boarder\n    Head -.-&gt;|knows| Servant\n\n    %% --- Styles ---\n    style Head fill:#f9f,stroke:#333,stroke-width:2px\n    style Spouse fill:#bbf,stroke:#333\n    style Child fill:#bbf,stroke:#333\n    style Boarder fill:#eee,stroke:#999\n    style Servant fill:#eee,stroke:#999\n<\/code><\/pre>\n<p>This graph highlights the multi-modal nature of historical memory. By using solid lines for core family ties and dashed lines for the &#8220;extended&#8221; household (Boarders and Servants), we maintain the distinction between biological lineage and social proximity. Note the bidirectional &#8220;spouse&#8221; arrows; in our graph, no one is a silent attribute\u2014everyone is a first-class node capable of pointing back to their connections.<\/p>\n<h2>The Engineering of Symmetry<\/h2>\n<p>In a true Knowledge Graph, relationships must be <strong>Symmetric<\/strong>. If the Scribe identifies a &#8220;Wife,&#8221; it shouldn&#8217;t just point her to the Head of Household; the Head must also point back to her.<\/p>\n<p>We implemented a <strong>Symmetric Linking Pipeline<\/strong> that ensures the graph is balanced. When the Scribe &#8220;forges&#8221; a link, it updates both entities simultaneously within a single atomic transaction.<\/p>\n<p>To build a graph that actually works, the Scribe must be unbiased. It doesn&#8217;t just link a &#8216;Wife&#8217; to a &#8216;Head&#8217;; it links them both as equals in a <code>spouse<\/code> relationship. This ensures that no matter which person the AI &#8216;looks&#8217; at first, it can find the other.<\/p>\n<pre><code class=\"language-python\"># The Scribe's Symmetric Linking Pipeline\nif rel_lower in (\"wife\", \"husband\"):\n    # Mirroring the census reality: Both partners are linked symmetrically\n    spouse_link = {\"@id\": head_id, \"relationshipDescription\": rel_raw}\n    spouse_back = {\"@id\": member_id, \"relationshipDescription\": rel_raw}\n\n    # Update Member -&gt; Head\n    if _add_to_relation(entity, \"spouse\", spouse_link):\n        links_created += 1\n    # Update Head -&gt; Member (Symmetry)\n    if _add_to_relation(head, \"spouse\", spouse_back):\n        links_created += 1\n<\/code><\/pre>\n<h2>Mapping the Block: The Dwelling as a Container<\/h2>\n<p>One of the most powerful tools we\u2019ve added is <code>search_by_dwelling<\/code>. By treating the physical house as a container, the Scribe can now &#8220;Map the Block.&#8221; We can ask the Scribe to show us everyone living at Dwelling #10, revealing multi-family boarding houses and the complex social hierarchies within.<\/p>\n<p>By combining this search with our <strong>Dry Run<\/strong> feature, the Scribe can &#8220;imagine&#8221; the social links of an entire neighborhood before committing them to the permanent archive.<\/p>\n<pre><code class=\"language-python\"># Mapping a multi-family dwelling via the MCP tool\ndwelling_data = mcp.call_tool(\"search_by_dwelling\", {\"dwelling_number\": 10})\n\n# Logic: Dwelling 10 contains everyone in the building\n# including Boarders and different Family Numbers.\n# Output Count: 11 residents\n# - Family 12: The Smith Family\n# - Family 13: The Miller Family\n# - Unaffiliated: John Doe (Boarder)\n<\/code><\/pre>\n<p>Because <code>search_by_dwelling<\/code> returns a structured list of all residents, the agent can iterate through multiple family units in a single pass, applying the graph-linking logic to the entire physical structure at once.<\/p>\n<pre><code class=\"language-mermaid\">graph TD\n    %% --- The Physical Container (Dwelling 10) ---\n    subgraph Building [\"Dwelling 10: The Physical Building\"]\n\n        %% --- Household A ---\n        subgraph Family12 [\"Family Number 12\"]\n            A1(Head: Farmer)\n            A2(Wife)\n            A3(Son)\n        end\n\n        %% --- Household B ---\n        subgraph Family13 [\"Family Number 13\"]\n            B1(Head: Blacksmith)\n            B2(Son)\n            B3(Daughter)\n        end\n\n        %% --- Unaffiliated ---\n        C1[Servant]\n        C2[Boarder]\n    end\n\n    %% --- Inter-Dwelling Links ---\n    A1 &lt;--&gt; B1\n    A1 &lt;--&gt; C1\n    B1 &lt;--&gt; C2\n\n    %% --- Styles ---\n    style Building fill:#eef,stroke:#333,stroke-width:2px\n    style Family12 fill:#f9f,stroke:#333\n    style Family13 fill:#bbf,stroke:#333\n    style A1,B1 fill:#f9f,stroke:#333,stroke-width:1px\n<\/code><\/pre>\n<p>Viewing history through the &#8220;Dwelling&#8221; lens reveals a different kind of truth. By treating the physical building as a parent container, the Scribe can group disparate family units (like Family 12 and 13 above) who shared the same roof. This &#8220;Mapping the Block&#8221; strategy allows an agent to infer social influence\u2014how a Boarder&#8217;s trade might influence the children of the family they live with, or how neighborhoods clustered by occupation.<\/p>\n<h2>Why the Graph is the Future<\/h2>\n<p>By building a <strong>Social Graph<\/strong>, we\u2019ve given the Digital Scribe a form of &#8220;Inference.&#8221; It no longer just knows who people are; it understands how they belong.<\/p>\n<p>This is the final foundation stone for the Digital Scribe. We have mastered <strong>Capture<\/strong>, <strong>Persistence<\/strong>, and <strong>Connectivity<\/strong>.<\/p>\n<h2>What&#8217;s Next?<\/h2>\n<p>The Digital Scribe is now a fully realized Knowledge Graph. We have mastered Capture, Persistence, and Connectivity. But a Sovereign system shouldn&#8217;t just live in the past. In our next entry, we\u2019re going to take a &#8216;Brain Break&#8217; to look at how this exact same architecture can be handed over to a modern challenge: helping a farmer pivot their harvest when the market shifts.<\/p>\n<p>The 1880 Archive was the training ground; the 2026 Vineyard is the mission.<\/p>\n<a class=\"synved-social-button synved-social-button-share synved-social-size-48 synved-social-resolution-single synved-social-provider-facebook nolightbox\" data-provider=\"facebook\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Facebook\" href=\"https:\/\/www.facebook.com\/sharer.php?u=https%3A%2F%2Fwww.kenwalger.com%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F1449&amp;t=Mapping%20the%20Social%20Graph&amp;s=100&amp;p[url]=https%3A%2F%2Fwww.kenwalger.com%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F1449&amp;p[images][0]=https%3A%2F%2Fwww.kenwalger.com%2Fblog%2Fwp-content%2Fuploads%2F2026%2F04%2Fblog-of-ken-w.-alger-69ea334bc97bc.png&amp;p[title]=Mapping%20the%20Social%20Graph\" style=\"font-size: 0px;width:48px;height:48px;margin:0;margin-bottom:5px;margin-right:5px\"><img loading=\"lazy\" decoding=\"async\" alt=\"Facebook\" title=\"Share on Facebook\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"48\" height=\"48\" style=\"display: inline;width:48px;height:48px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/www.kenwalger.com\/blog\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/96x96\/facebook.png\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-48 synved-social-resolution-single synved-social-provider-twitter nolightbox\" data-provider=\"twitter\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Twitter\" href=\"https:\/\/twitter.com\/intent\/tweet?url=https%3A%2F%2Fwww.kenwalger.com%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F1449&amp;text=Hey%20check%20this%20out\" style=\"font-size: 0px;width:48px;height:48px;margin:0;margin-bottom:5px;margin-right:5px\"><img loading=\"lazy\" decoding=\"async\" alt=\"twitter\" title=\"Share on Twitter\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"48\" height=\"48\" style=\"display: inline;width:48px;height:48px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/www.kenwalger.com\/blog\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/96x96\/twitter.png\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-48 synved-social-resolution-single synved-social-provider-reddit nolightbox\" data-provider=\"reddit\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Reddit\" href=\"https:\/\/www.reddit.com\/submit?url=https%3A%2F%2Fwww.kenwalger.com%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F1449&amp;title=Mapping%20the%20Social%20Graph\" style=\"font-size: 0px;width:48px;height:48px;margin:0;margin-bottom:5px;margin-right:5px\"><img loading=\"lazy\" decoding=\"async\" alt=\"reddit\" title=\"Share on Reddit\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"48\" height=\"48\" style=\"display: inline;width:48px;height:48px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/www.kenwalger.com\/blog\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/96x96\/reddit.png\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-48 synved-social-resolution-single synved-social-provider-linkedin nolightbox\" data-provider=\"linkedin\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Linkedin\" href=\"https:\/\/www.linkedin.com\/shareArticle?mini=true&amp;url=https%3A%2F%2Fwww.kenwalger.com%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F1449&amp;title=Mapping%20the%20Social%20Graph\" style=\"font-size: 0px;width:48px;height:48px;margin:0;margin-bottom:5px;margin-right:5px\"><img loading=\"lazy\" decoding=\"async\" alt=\"linkedin\" title=\"Share on Linkedin\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"48\" height=\"48\" style=\"display: inline;width:48px;height:48px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/www.kenwalger.com\/blog\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/96x96\/linkedin.png\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-48 synved-social-resolution-single synved-social-provider-mail nolightbox\" data-provider=\"mail\" rel=\"nofollow\" title=\"Share by email\" href=\"mailto:?subject=Mapping%20the%20Social%20Graph&amp;body=Hey%20check%20this%20out:%20https%3A%2F%2Fwww.kenwalger.com%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F1449\" style=\"font-size: 0px;width:48px;height:48px;margin:0;margin-bottom:5px\"><img loading=\"lazy\" decoding=\"async\" alt=\"mail\" title=\"Share by email\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"48\" height=\"48\" style=\"display: inline;width:48px;height:48px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/www.kenwalger.com\/blog\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/96x96\/mail.png\" \/><\/a>","protected":false},"excerpt":{"rendered":"<p>In our previous post, we built the Knowledge Archive, a durable, atomic vault for historical data. We moved from &#8220;strings to things&#8221; by adopting the Schema.org vocabulary. But even with a vault full of people, the Scribe was still seeing individuals in isolation. History isn&#8217;t just a list of names; it\u2019s a web of Relationships. &hellip; <a href=\"https:\/\/www.kenwalger.com\/blog\/ai\/building-social-graphs-with-ai-agents\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Mapping the Social Graph&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":1504,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"pmpro_default_level":"","_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[1669,1670],"tags":[],"yst_prominent_words":[1243],"class_list":["post-1449","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ai","category-mcp","pmpro-has-access"],"jetpack_featured_media_url":"https:\/\/www.kenwalger.com\/blog\/wp-content\/uploads\/2026\/04\/blog-of-ken-w.-alger-69ea334bc97bc.png","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p8lx70-nn","jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/posts\/1449","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/comments?post=1449"}],"version-history":[{"count":2,"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/posts\/1449\/revisions"}],"predecessor-version":[{"id":1451,"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/posts\/1449\/revisions\/1451"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/media\/1504"}],"wp:attachment":[{"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/media?parent=1449"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/categories?post=1449"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/tags?post=1449"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/www.kenwalger.com\/blog\/wp-json\/wp\/v2\/yst_prominent_words?post=1449"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}