[{"data":1,"prerenderedAt":2323},["ShallowReactive",2],{"blog-posts-all":3},[4,453,1583],{"_path":5,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":9,"description":10,"date":11,"tags":12,"cover":18,"author":19,"authorIntro":20,"body":21,"_type":447,"_id":448,"_source":449,"_file":450,"_stem":451,"_extension":452},"\u002Fposts\u002F002-odin","posts",false,"","Odín: the case that made everything click","Origin story: four months configuring a CRM for a client, one honest question about knowledge transfer, and five minutes that replaced one full day of bulk configuration work. This is what pushed me to study agentic AI seriously.","2026-05-23",[13,14,15,16,17],"agents","case-study","knowledge-transfer","origin","openclaw","\u002Fimages\u002Fposts\u002Fodin-cover.png","Pablo Suárez Peña","I build and refine AI agents with OpenClaw—in client work and on personal projects where I can take more risk. Odín was not a planned experiment. It was the moment that forced me to take agentic AI seriously—and this is the account of how it happened.",{"type":22,"children":23,"toc":437},"root",[24,32,36,43,48,61,66,71,86,91,94,100,105,117,122,135,138,144,149,154,188,193,196,202,207,219,228,236,244,249,254,259,262,268,273,292,297,305,313,318,321,327,332,342,352,362,372,375,381,386,398,403,408,416,419],{"type":25,"tag":26,"props":27,"children":28},"element","p",{},[29],{"type":30,"value":31},"text","Not a lab experiment, not a proof of concept. A real client, a real constraint, and the right question asked at the right moment.",{"type":25,"tag":33,"props":34,"children":35},"hr",{},[],{"type":25,"tag":37,"props":38,"children":40},"h2",{"id":39},"four-months-inside-a-crm",[41],{"type":30,"value":42},"Four months inside a CRM",{"type":25,"tag":26,"props":44,"children":45},{},[46],{"type":30,"value":47},"The starting point was as ordinary as they come: a client, a CRM we were customising for them, and the need to automate processes that were consuming time nobody had.",{"type":25,"tag":26,"props":49,"children":50},{},[51,53,59],{"type":30,"value":52},"I spent roughly four months learning that CRM properly—its logic, its limits, its shortcuts, its edge cases. Not learning to use it: learning ",{"type":25,"tag":54,"props":55,"children":56},"em",{},[57],{"type":30,"value":58},"why",{"type":30,"value":60}," it worked the way it did, what each configuration decision implied downstream, and how to map its technical possibilities onto the client's actual requirements.",{"type":25,"tag":26,"props":62,"children":63},{},[64],{"type":30,"value":65},"By the end of that period I had something valuable: a precise mental model of how the whole system held together. I knew what to touch, in what order, what any given adjustment would cost or unlock. The kind of tacit knowledge that normally lives in one person's head—and forces everyone else to start from scratch whenever that person is unavailable.",{"type":25,"tag":26,"props":67,"children":68},{},[69],{"type":30,"value":70},"Two observations surfaced that, at the time, seemed unrelated:",{"type":25,"tag":72,"props":73,"children":74},"ol",{},[75,81],{"type":25,"tag":76,"props":77,"children":78},"li",{},[79],{"type":30,"value":80},"That accumulated knowledge needed to live somewhere structured and reusable.",{"type":25,"tag":76,"props":82,"children":83},{},[84],{"type":30,"value":85},"The same knowledge could serve future projects without repeating the same learning curve.",{"type":25,"tag":26,"props":87,"children":88},{},[89],{"type":30,"value":90},"I did not yet know how to connect those two things. But the question had been asked.",{"type":25,"tag":33,"props":92,"children":93},{},[],{"type":25,"tag":37,"props":95,"children":97},{"id":96},"the-question-that-changed-the-framing",[98],{"type":30,"value":99},"The question that changed the framing",{"type":25,"tag":26,"props":101,"children":102},{},[103],{"type":30,"value":104},"The project eventually reached a phase that required high-complexity, highly-specific changes. Changes that were straightforward in principle but depended on a layer of context only I had internalised. That is when I asked what seemed like a straightforward team-management question—but turned out to be something else entirely:",{"type":25,"tag":106,"props":107,"children":108},"blockquote",{},[109],{"type":25,"tag":26,"props":110,"children":111},{},[112],{"type":25,"tag":54,"props":113,"children":114},{},[115],{"type":30,"value":116},"\"If I am not here, can someone else do this? Probably yes—but how long will they spend learning what I already know? They would need to understand the CRM, how I have been configuring it, how it works internally, and also the specific way this particular client needs it done. Does someone have to lose that time again?\"",{"type":25,"tag":26,"props":118,"children":119},{},[120],{"type":30,"value":121},"The honest answer was: no. That road had already been travelled. All of that knowledge could—and should—be available in a different form. Not locked in my head, not scattered across notes that someone else would have to decode. Active, queryable, ready to apply.",{"type":25,"tag":26,"props":123,"children":124},{},[125,127,133],{"type":30,"value":126},"That reasoning is what led us to build ",{"type":25,"tag":128,"props":129,"children":130},"strong",{},[131],{"type":30,"value":132},"Odín",{"type":30,"value":134},".",{"type":25,"tag":33,"props":136,"children":137},{},[],{"type":25,"tag":37,"props":139,"children":141},{"id":140},"what-odín-was-supposed-to-do",[142],{"type":30,"value":143},"What Odín was supposed to do",{"type":25,"tag":26,"props":145,"children":146},{},[147],{"type":30,"value":148},"The idea was straightforward to state, harder to execute: transfer everything learned over those four months into an AI agent that could operate with that knowledge autonomously. Not a passive knowledge base to consult. A system that could execute real tasks using that context.",{"type":25,"tag":26,"props":150,"children":151},{},[152],{"type":30,"value":153},"Looking back, three things determined how well it worked — or didn't:",{"type":25,"tag":155,"props":156,"children":157},"ul",{},[158,168,178],{"type":25,"tag":76,"props":159,"children":160},{},[161,166],{"type":25,"tag":128,"props":162,"children":163},{},[164],{"type":30,"value":165},"Transferred knowledge",{"type":30,"value":167}," — the CRM's logic, the client's requirements, the configuration patterns accumulated over four months, structured in a way the model could use.",{"type":25,"tag":76,"props":169,"children":170},{},[171,176],{"type":25,"tag":128,"props":172,"children":173},{},[174],{"type":30,"value":175},"A clear specification",{"type":30,"value":177}," — explicit instructions for what the agent should do, in what order, and with what quality criteria. Not just \"here is what I know\"—here is exactly what you need to do with it.",{"type":25,"tag":76,"props":179,"children":180},{},[181,186],{"type":25,"tag":128,"props":182,"children":183},{},[184],{"type":30,"value":185},"Defined limits",{"type":30,"value":187}," — the operational boundaries within which the agent was allowed to act. Not restrictions imposed after the fact. Guardrails designed alongside the task, as part of the design.",{"type":25,"tag":26,"props":189,"children":190},{},[191],{"type":30,"value":192},"We did not start with all three in place. We learned their weight by experiencing what happened when each one was missing.",{"type":25,"tag":33,"props":194,"children":195},{},[],{"type":25,"tag":37,"props":197,"children":199},{"id":198},"how-we-actually-built-it",[200],{"type":30,"value":201},"How we actually built it",{"type":25,"tag":26,"props":203,"children":204},{},[205],{"type":30,"value":206},"The honest version: we built it the old-school way.",{"type":25,"tag":26,"props":208,"children":209},{},[210,212,217],{"type":30,"value":211},"No structured files, no tiered architecture, no separation between identity and operational context. We sat down with the agent and told it what it needed to know as we went. ",{"type":25,"tag":54,"props":213,"children":214},{},[215],{"type":30,"value":216},"You have access to this. You can modify this. You can load this.",{"type":30,"value":218}," Every time it completed a step we told it to save what it had just done to memory. It was, essentially, a running session journal dressed up as an agent.",{"type":25,"tag":26,"props":220,"children":221},{},[222],{"type":25,"tag":223,"props":224,"children":227},"img",{"alt":225,"src":226},"A complex task instruction ending with \"save the automation process to memory\" — the pattern that defined how Odín was built","\u002Fimages\u002Fposts\u002Fodin-memory-01.png",[],{"type":25,"tag":26,"props":229,"children":230},{},[231],{"type":25,"tag":223,"props":232,"children":235},{"alt":233,"src":234},"The same pattern reduced to its most mechanical form — save this to memory, confirmed","\u002Fimages\u002Fposts\u002Fodin-memory-02.png",[],{"type":25,"tag":26,"props":237,"children":238},{},[239],{"type":25,"tag":54,"props":240,"children":241},{},[242],{"type":30,"value":243},"The recurring pattern: complete a step, save it to memory. Session after session, the same reflex. It worked — until it didn't.",{"type":25,"tag":26,"props":245,"children":246},{},[247],{"type":30,"value":248},"It worked. That was the surprising part. The knowledge was there—scattered across memory entries and session notes rather than organised in any principled way—but it was there. The agent could find it and use it. Badly structured context still beats no context.",{"type":25,"tag":26,"props":250,"children":251},{},[252],{"type":30,"value":253},"What we did not realise at the time was that we were accumulating technical debt inside the agent. Every new task added another memory entry. There was no ownership model—the same piece of information might appear three times in slightly different forms. There were no guardrails, no defined scope, no explicit stopping conditions. The agent would do what we asked, but we were never entirely sure it would do exactly that and nothing else.",{"type":25,"tag":26,"props":255,"children":256},{},[257],{"type":30,"value":258},"That messy first version is what produced the five-minute result. And it is also what made it clear that the approach did not scale. Odín worked because the task was contained and we were watching closely. It would not have survived a more complex brief, a longer run, or a session we were not present for. Correcting those problems—properly—is what eventually led to the way we build agents now.",{"type":25,"tag":33,"props":260,"children":261},{},[],{"type":25,"tag":37,"props":263,"children":265},{"id":264},"five-minutes-instead-of-one-day",[266],{"type":30,"value":267},"Five minutes instead of one day",{"type":25,"tag":26,"props":269,"children":270},{},[271],{"type":30,"value":272},"And yet — it worked.",{"type":25,"tag":26,"props":274,"children":275},{},[276,278,283,285,290],{"type":30,"value":277},"With no prior depth in agentic development—configuring largely by instinct, learning as we went, carrying more questions than certainties—in under a week Odín was completing in ",{"type":25,"tag":128,"props":279,"children":280},{},[281],{"type":30,"value":282},"five minutes",{"type":30,"value":284}," what had previously taken ",{"type":25,"tag":128,"props":286,"children":287},{},[288],{"type":30,"value":289},"one full working day",{"type":30,"value":291},": bulk data loading, field mapping, label configuration, automation flows. The kind of CRM configuration work that is not technically complex but is slow, detail-heavy, and entirely dependent on knowing exactly how this particular client's setup was structured.",{"type":25,"tag":26,"props":293,"children":294},{},[295],{"type":30,"value":296},"This was not a demo that ran once and could not be reproduced. It was the result of depositing the right knowledge, specifying the task clearly, and containing the agent's scope precisely enough to trust it. Three things that, combined, produced something reliable.",{"type":25,"tag":26,"props":298,"children":299},{},[300],{"type":25,"tag":223,"props":301,"children":304},{"alt":302,"src":303},"Odín creating 59 CRM opportunities from an Excel file, with stages assigned by service type — triggered by a single Discord message","\u002Fimages\u002Fposts\u002Fodin-in-action.png",[],{"type":25,"tag":26,"props":306,"children":307},{},[308],{"type":25,"tag":54,"props":309,"children":310},{},[311],{"type":30,"value":312},"Odín processing a 59-row Excel file and creating one CRM opportunity per row, with stages assigned by service type — from a single Discord message.",{"type":25,"tag":26,"props":314,"children":315},{},[316],{"type":30,"value":317},"The first time we watched it execute in real time what would have taken a full day, there was a moment of silence. The kind that means something has shifted.",{"type":25,"tag":33,"props":319,"children":320},{},[],{"type":25,"tag":37,"props":322,"children":324},{"id":323},"what-the-process-taught-us",[325],{"type":30,"value":326},"What the process taught us",{"type":25,"tag":26,"props":328,"children":329},{},[330],{"type":30,"value":331},"The Odín build was brief. The lessons were not.",{"type":25,"tag":26,"props":333,"children":334},{},[335,340],{"type":25,"tag":128,"props":336,"children":337},{},[338],{"type":30,"value":339},"Accumulated knowledge can be transferred—and an agent can work with it.",{"type":30,"value":341}," The four months of CRM configuration were not wasted when we handed the work to an agent. The field dependencies, the label hierarchies, the flow logic — all of it had been described to Odín in scattered session notes, but it was there. The agent could retrieve it and act on it. That was the first proof that the learning curve does not have to be walked twice.",{"type":25,"tag":26,"props":343,"children":344},{},[345,350],{"type":25,"tag":128,"props":346,"children":347},{},[348],{"type":30,"value":349},"Knowledge alone is not enough—it needs a specification.",{"type":30,"value":351}," Early on, we gave Odín access to everything and told it to load the data. Without a clear order of operations, it would occasionally apply labels before the relevant fields existed, or configure flows that referenced contacts that had not been imported yet. The knowledge was correct. The sequence was not. Adding an explicit step order — field creation first, then data load, then labels, then flows — was what made the output reliable.",{"type":25,"tag":26,"props":353,"children":354},{},[355,360],{"type":25,"tag":128,"props":356,"children":357},{},[358],{"type":30,"value":359},"Limits are part of the design, not an afterthought.",{"type":30,"value":361}," We asked Odín to configure a set of labels. It configured them — and then started applying them to existing records it inferred should have them. That inference was not wrong. But it was not asked for, and it changed data we had not reviewed. Without a \"do not act beyond the explicit task\" boundary, the agent was helpful in ways we had not authorised. Guardrails are not restrictions that reduce what the agent can do. They are the condition that makes it possible to trust what it does.",{"type":25,"tag":26,"props":363,"children":364},{},[365,370],{"type":25,"tag":128,"props":366,"children":367},{},[368],{"type":30,"value":369},"You have to verify, not assume.",{"type":30,"value":371}," Because we were building Odín's context in real time — telling it to save each completed step to memory — we had no way to know, session to session, whether what it had stored was accurate. We would start a new session, ask Odín to continue, and occasionally find that it had saved a summary that slightly misrepresented what had actually been done. Not a lie — a compression. And a compression of configuration state is enough to break the next step. Verifying what it had stored, not just trusting the memory log, became a habit.",{"type":25,"tag":33,"props":373,"children":374},{},[],{"type":25,"tag":37,"props":376,"children":378},{"id":377},"what-clicked",[379],{"type":30,"value":380},"What clicked",{"type":25,"tag":26,"props":382,"children":383},{},[384],{"type":30,"value":385},"Odín was not the first step in a planned programme of study. It was the moment that made studying feel necessary.",{"type":25,"tag":26,"props":387,"children":388},{},[389,391,396],{"type":30,"value":390},"Before Odín, agentic AI was interesting in the abstract—worth watching, worth reading about. After Odín, it became a concrete question with concrete stakes: ",{"type":25,"tag":54,"props":392,"children":393},{},[394],{"type":30,"value":395},"what does it actually take to make this work well?",{"type":30,"value":397}," Not in a demo, not in a controlled environment, but with a real client, a real CRM, and a real standard of output.",{"type":25,"tag":26,"props":399,"children":400},{},[401],{"type":30,"value":402},"That question did not have a short answer. It opened into harder ones: how do you structure knowledge so an agent can use it reliably? How do you know when it is doing what you asked, and when it is only appearing to?",{"type":25,"tag":26,"props":404,"children":405},{},[406],{"type":30,"value":407},"Those are the questions this site and this work are built around. Odín was not the answer—it was the moment the questions became unavoidable. And the only way to answer them properly was to keep building, keep observing, and keep documenting what held and what did not.",{"type":25,"tag":106,"props":409,"children":410},{},[411],{"type":25,"tag":26,"props":412,"children":413},{},[414],{"type":30,"value":415},"The five minutes were not the result. The five minutes were the proof that the questions were worth asking.",{"type":25,"tag":33,"props":417,"children":418},{},[],{"type":25,"tag":26,"props":420,"children":421},{},[422],{"type":25,"tag":54,"props":423,"children":424},{},[425,427,436],{"type":30,"value":426},"Odín was the start. The case studies that came after are documented at ",{"type":25,"tag":428,"props":429,"children":433},"a",{"href":430,"rel":431},"https:\u002F\u002Fbuild-your-agents.com",[432],"nofollow",[434],{"type":30,"value":435},"build-your-agents.com",{"type":30,"value":134},{"title":8,"searchDepth":438,"depth":438,"links":439},2,[440,441,442,443,444,445,446],{"id":39,"depth":438,"text":42},{"id":96,"depth":438,"text":99},{"id":140,"depth":438,"text":143},{"id":198,"depth":438,"text":201},{"id":264,"depth":438,"text":267},{"id":323,"depth":438,"text":326},{"id":377,"depth":438,"text":380},"markdown","content:posts:002-Odin.md","content","posts\u002F002-Odin.md","posts\u002F002-Odin","md",{"_path":454,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":455,"description":456,"date":457,"tags":458,"filesTouched":461,"cover":468,"author":19,"authorIntro":469,"body":470,"_type":447,"_id":1580,"_source":449,"_file":1581,"_stem":1582,"_extension":452},"\u002Fposts\u002F001-sabrina","Sabrina: seven-file B2B prospecting","Case study: from a dense PDF pipeline (Discord, LinkedIn, Unipile, Lusha, Odoo) to seven markdown files the agent can run inside—filing tiers, deduplicating nine first-draft overlaps, and writing SOUL from what the spec never said out loud.","2026-05-15",[13,459,14,17,460],"b2b","odoo",[462,463,13,464,465,466,467],"soul","identity","user","tools","memory","heartbeat","\u002Fimages\u002Fposts\u002Fsabrina-cover.png","I build and refine AI agents with OpenClaw—in client work and on personal projects where I can take more risk. This case study is how we turned a B2B prospecting spec into seven files Sabrina can run inside; I publish notes like this to clarify my own thinking and in case they help someone facing a similar filing problem.",{"type":22,"children":471,"toc":1566},[472,477,482,485,491,496,501,509,514,517,523,528,538,543,551,556,559,565,583,588,736,746,749,755,760,765,770,818,831,836,899,911,944,949,952,958,970,978,990,995,1004,1009,1012,1018,1023,1041,1053,1166,1171,1174,1180,1192,1211,1230,1235,1245,1255,1265,1275,1285,1290,1293,1299,1304,1312,1317,1320,1326,1331,1339,1351,1356,1359,1365,1370,1403,1422,1448,1453,1456,1462,1472,1482,1497,1507,1524,1532,1535,1541,1546,1549],{"type":25,"tag":26,"props":473,"children":474},{},[475],{"type":30,"value":476},"A walkthrough of every decision along the way — what went where, what broke in the first draft, and what the spec alone could not tell us.",{"type":25,"tag":26,"props":478,"children":479},{},[480],{"type":30,"value":481},"Sabrina is being built for a commercial team that needs qualified B2B leads in Odoo without manually chaining LinkedIn search, enrichment, and CRM updates after every command.",{"type":25,"tag":33,"props":483,"children":484},{},[],{"type":25,"tag":37,"props":486,"children":488},{"id":487},"the-brief",[489],{"type":30,"value":490},"The brief",{"type":25,"tag":26,"props":492,"children":493},{},[494],{"type":30,"value":495},"The starting point was a thorough functional specification for the pipeline below — six phases, decision tables, error handling, rate limits, deduplication rules, field mappings. Everything you would want before writing a line of code.",{"type":25,"tag":26,"props":497,"children":498},{},[499],{"type":30,"value":500},"The full pipeline in one line:",{"type":25,"tag":106,"props":502,"children":503},{},[504],{"type":25,"tag":26,"props":505,"children":506},{},[507],{"type":30,"value":508},"Discord command → LinkedIn search (Unipile) → contact enrichment (Lusha) → Odoo CRM registration → LinkedIn connection request → Discord summary.",{"type":25,"tag":26,"props":510,"children":511},{},[512],{"type":30,"value":513},"The job was not to build the pipeline. It was to translate it into seven files that the agent could actually live inside — and to think carefully about what belongs where.",{"type":25,"tag":33,"props":515,"children":516},{},[],{"type":25,"tag":37,"props":518,"children":520},{"id":519},"step-one-reading-the-spec-as-a-filing-problem",[521],{"type":30,"value":522},"Step one: reading the spec as a filing problem",{"type":25,"tag":26,"props":524,"children":525},{},[526],{"type":30,"value":527},"The first instinct when faced with a detailed spec is to start writing files immediately. That was a mistake. The first draft was produced too fast, with content placed by feel rather than by principle — and it showed.",{"type":25,"tag":26,"props":529,"children":530},{},[531,533],{"type":30,"value":532},"Instead of starting over blindly, the right move was to step back and ask a different question about each section of the spec: ",{"type":25,"tag":54,"props":534,"children":535},{},[536],{"type":30,"value":537},"what kind of information is this?",{"type":25,"tag":26,"props":539,"children":540},{},[541],{"type":30,"value":542},"There are roughly four kinds of information in any agent specification. They map to tiers. And the tiers have a direction: lower tiers are read by higher ones, never the other way around.",{"type":25,"tag":26,"props":544,"children":545},{},[546],{"type":25,"tag":223,"props":547,"children":550},{"alt":548,"src":549},"The four-tier dependency hierarchy","\u002Fimages\u002Fdiagrams\u002Fdiagram-01-tiers.jpg",[],{"type":25,"tag":26,"props":552,"children":553},{},[554],{"type":30,"value":555},"With this mental model, each section of the specification gets tagged: is this identity? orchestration? operational? or state? That exercise alone makes most of the filing decisions obvious — but it has to happen before writing, not after.",{"type":25,"tag":33,"props":557,"children":558},{},[],{"type":25,"tag":37,"props":560,"children":562},{"id":561},"step-two-the-seven-files-what-actually-went-where",[563],{"type":30,"value":564},"Step two: the seven files — what actually went where",{"type":25,"tag":26,"props":566,"children":567},{},[568,570,575,577,582],{"type":30,"value":569},"Here is what the spec revealed immediately: the specification was almost entirely operational. Very little of it was about who Sabrina ",{"type":25,"tag":54,"props":571,"children":572},{},[573],{"type":30,"value":574},"is",{"type":30,"value":576}," — most of it was about what Sabrina ",{"type":25,"tag":54,"props":578,"children":579},{},[580],{"type":30,"value":581},"does",{"type":30,"value":134},{"type":25,"tag":26,"props":584,"children":585},{},[586],{"type":30,"value":587},"That is a common pattern in agent design. The identity layer gets neglected because it feels soft. But it is the identity layer that governs behaviour when the pipeline does not give a clear answer.",{"type":25,"tag":589,"props":590,"children":591},"table",{},[592,611],{"type":25,"tag":593,"props":594,"children":595},"thead",{},[596],{"type":25,"tag":597,"props":598,"children":599},"tr",{},[600,606],{"type":25,"tag":601,"props":602,"children":603},"th",{},[604],{"type":30,"value":605},"File",{"type":25,"tag":601,"props":607,"children":608},{},[609],{"type":30,"value":610},"What lives there",{"type":25,"tag":612,"props":613,"children":614},"tbody",{},[615,634,651,668,685,702,719],{"type":25,"tag":597,"props":616,"children":617},{},[618,629],{"type":25,"tag":619,"props":620,"children":621},"td",{},[622],{"type":25,"tag":623,"props":624,"children":626},"code",{"className":625},[],[627],{"type":30,"value":628},"SOUL.md",{"type":25,"tag":619,"props":630,"children":631},{},[632],{"type":30,"value":633},"Voice, values, hard limits. The five principles Sabrina applies when no rule resolves the situation.",{"type":25,"tag":597,"props":635,"children":636},{},[637,646],{"type":25,"tag":619,"props":638,"children":639},{},[640],{"type":25,"tag":623,"props":641,"children":643},{"className":642},[],[644],{"type":30,"value":645},"IDENTITY.md",{"type":25,"tag":619,"props":647,"children":648},{},[649],{"type":30,"value":650},"Metadata and routing. Model config, session settings, integration map. The only place credentials are referenced by name.",{"type":25,"tag":597,"props":652,"children":653},{},[654,663],{"type":25,"tag":619,"props":655,"children":656},{},[657],{"type":25,"tag":623,"props":658,"children":660},{"className":659},[],[661],{"type":30,"value":662},"AGENTS.md",{"type":25,"tag":619,"props":664,"children":665},{},[666],{"type":30,"value":667},"The conductor. Session boot order, the six-phase pipeline as executable pseudocode, decision rules table, escalation paths.",{"type":25,"tag":597,"props":669,"children":670},{},[671,680],{"type":25,"tag":619,"props":672,"children":673},{},[674],{"type":25,"tag":623,"props":675,"children":677},{"className":676},[],[678],{"type":30,"value":679},"USER.md",{"type":25,"tag":619,"props":681,"children":682},{},[683],{"type":30,"value":684},"Two user profiles: commercial and admin. Onboarding checklist, every command, every message the commercial can receive.",{"type":25,"tag":597,"props":686,"children":687},{},[688,697],{"type":25,"tag":619,"props":689,"children":690},{},[691],{"type":25,"tag":623,"props":692,"children":694},{"className":693},[],[695],{"type":30,"value":696},"MEMORY.md",{"type":25,"tag":619,"props":698,"children":699},{},[700],{"type":30,"value":701},"Evergreen facts. Confirmed pipeline rules, Odoo configuration, known operational patterns, credentials references.",{"type":25,"tag":597,"props":703,"children":704},{},[705,714],{"type":25,"tag":619,"props":706,"children":707},{},[708],{"type":25,"tag":623,"props":709,"children":711},{"className":710},[],[712],{"type":30,"value":713},"HEARTBEAT.md",{"type":25,"tag":619,"props":715,"children":716},{},[717],{"type":30,"value":718},"Scheduled tasks. API health checks every 15 minutes during active Jobs. Daily rate-limit resets. Weekly lead summaries.",{"type":25,"tag":597,"props":720,"children":721},{},[722,731],{"type":25,"tag":619,"props":723,"children":724},{},[725],{"type":25,"tag":623,"props":726,"children":728},{"className":727},[],[729],{"type":30,"value":730},"TOOLS.md",{"type":25,"tag":619,"props":732,"children":733},{},[734],{"type":30,"value":735},"Complete database schema, every API tool with parameters and error handling, the Lusha enrichment decision tree.",{"type":25,"tag":26,"props":737,"children":738},{},[739,744],{"type":25,"tag":623,"props":740,"children":742},{"className":741},[],[743],{"type":30,"value":730},{"type":30,"value":745}," is the largest and most specific file. It is the only file that changes if an API endpoint changes.",{"type":25,"tag":33,"props":747,"children":748},{},[],{"type":25,"tag":37,"props":750,"children":752},{"id":751},"step-three-the-first-draft-had-nine-duplicates",[753],{"type":30,"value":754},"Step three: the first draft had nine duplicates",{"type":25,"tag":26,"props":756,"children":757},{},[758],{"type":30,"value":759},"Here is what the first draft actually looked like: nine areas of duplicated content. Five were exact copies of the same information in two files. Four were partial overlaps where the same rule appeared at different levels of detail.",{"type":25,"tag":26,"props":761,"children":762},{},[763],{"type":30,"value":764},"This was not caught until reading all seven files side by side — something that sounds obvious but is easy to skip when you are writing file by file. The duplicates were invisible until you looked at the whole picture at once.",{"type":25,"tag":26,"props":766,"children":767},{},[768],{"type":30,"value":769},"The most glaring example was the LinkedIn rate limit. It appeared in four places:",{"type":25,"tag":155,"props":771,"children":772},{},[773,785,796,807],{"type":25,"tag":76,"props":774,"children":775},{},[776,778,783],{"type":30,"value":777},"In ",{"type":25,"tag":623,"props":779,"children":781},{"className":780},[],[782],{"type":30,"value":696},{"type":30,"value":784}," as a rule: \"20 invitations\u002Fday\u002Faccount\"",{"type":25,"tag":76,"props":786,"children":787},{},[788,789,794],{"type":30,"value":777},{"type":25,"tag":623,"props":790,"children":792},{"className":791},[],[793],{"type":30,"value":628},{"type":30,"value":795}," as a principle: \"protect the commercial's LinkedIn account\"",{"type":25,"tag":76,"props":797,"children":798},{},[799,800,805],{"type":30,"value":777},{"type":25,"tag":623,"props":801,"children":803},{"className":802},[],[804],{"type":30,"value":730},{"type":30,"value":806}," as implementation: \"queue if exceeded, abort if account restricted\"",{"type":25,"tag":76,"props":808,"children":809},{},[810,811,816],{"type":30,"value":777},{"type":25,"tag":623,"props":812,"children":814},{"className":813},[],[815],{"type":30,"value":713},{"type":30,"value":817}," as a monitoring task: \"alert at 75%, stop at 100%\"",{"type":25,"tag":26,"props":819,"children":820},{},[821,823,829],{"type":30,"value":822},"At first glance this looks reasonable — each file adds a different perspective. But the number ",{"type":25,"tag":623,"props":824,"children":826},{"className":825},[],[827],{"type":30,"value":828},"20",{"type":30,"value":830}," appeared verbatim in three of those files. If that limit changes, you need to remember to update three separate files. That is how agents start behaving in contradictory ways in production.",{"type":25,"tag":26,"props":832,"children":833},{},[834],{"type":30,"value":835},"The fix was to give each file a single voice and a single ownership:",{"type":25,"tag":155,"props":837,"children":838},{},[839,855,870,884],{"type":25,"tag":76,"props":840,"children":841},{},[842,846,848,853],{"type":25,"tag":128,"props":843,"children":844},{},[845],{"type":30,"value":696},{"type":30,"value":847}," owns ",{"type":25,"tag":54,"props":849,"children":850},{},[851],{"type":30,"value":852},"what",{"type":30,"value":854}," the rule is (the number: 20 invitations\u002Fday)",{"type":25,"tag":76,"props":856,"children":857},{},[858,862,863,868],{"type":25,"tag":128,"props":859,"children":860},{},[861],{"type":30,"value":730},{"type":30,"value":847},{"type":25,"tag":54,"props":864,"children":865},{},[866],{"type":30,"value":867},"how",{"type":30,"value":869}," it is implemented (queue, abort, notify)",{"type":25,"tag":76,"props":871,"children":872},{},[873,877,878,882],{"type":25,"tag":128,"props":874,"children":875},{},[876],{"type":30,"value":628},{"type":30,"value":847},{"type":25,"tag":54,"props":879,"children":880},{},[881],{"type":30,"value":58},{"type":30,"value":883}," it matters (the principle, not the number)",{"type":25,"tag":76,"props":885,"children":886},{},[887,891,892,897],{"type":25,"tag":128,"props":888,"children":889},{},[890],{"type":30,"value":713},{"type":30,"value":847},{"type":25,"tag":54,"props":893,"children":894},{},[895],{"type":30,"value":896},"when",{"type":30,"value":898}," to act on it (75% and 100% thresholds)",{"type":25,"tag":26,"props":900,"children":901},{},[902,904,909],{"type":30,"value":903},"After deduplication, the number ",{"type":25,"tag":623,"props":905,"children":907},{"className":906},[],[908],{"type":30,"value":828},{"type":30,"value":910}," appears in exactly one file. The others reference the concept without repeating the value.",{"type":25,"tag":26,"props":912,"children":913},{},[914,916,921,923,928,930,935,937,942],{"type":30,"value":915},"The database schema had the same problem. It appeared partially in ",{"type":25,"tag":623,"props":917,"children":919},{"className":918},[],[920],{"type":30,"value":696},{"type":30,"value":922},", partially in ",{"type":25,"tag":623,"props":924,"children":926},{"className":925},[],[927],{"type":30,"value":730},{"type":30,"value":929},", and was referenced in ",{"type":25,"tag":623,"props":931,"children":933},{"className":932},[],[934],{"type":30,"value":662},{"type":30,"value":936},". After the audit, the complete schema lives only in ",{"type":25,"tag":623,"props":938,"children":940},{"className":939},[],[941],{"type":30,"value":730},{"type":30,"value":943},". Every other file that needs to reference a table names it without reproducing its structure.",{"type":25,"tag":26,"props":945,"children":946},{},[947],{"type":30,"value":948},"Duplicates are not just redundant. They are the symptom of unclear ownership. Every duplicate found during this process was evidence of a decision that had not been made yet about which file owns that piece of information.",{"type":25,"tag":33,"props":950,"children":951},{},[],{"type":25,"tag":37,"props":953,"children":955},{"id":954},"step-four-the-pipeline-as-agentsmd",[956],{"type":30,"value":957},"Step four: the pipeline as AGENTS.md",{"type":25,"tag":26,"props":959,"children":960},{},[961,963,968],{"type":30,"value":962},"The most important single file is ",{"type":25,"tag":623,"props":964,"children":966},{"className":965},[],[967],{"type":30,"value":662},{"type":30,"value":969},". It is where the six-phase pipeline becomes something the model can actually execute — not prose describing the process, but structured pseudocode with explicit loop conditions, decision branches, and escalation points.",{"type":25,"tag":26,"props":971,"children":972},{},[973],{"type":25,"tag":223,"props":974,"children":977},{"alt":975,"src":976},"Sabrina's six-phase pipeline","\u002Fimages\u002Fdiagrams\u002Fdiagram-02-pipeline.jpg",[],{"type":25,"tag":26,"props":979,"children":980},{},[981,983,988],{"type":30,"value":982},"The key insight in ",{"type":25,"tag":623,"props":984,"children":986},{"className":985},[],[987],{"type":30,"value":662},{"type":30,"value":989}," is the loop condition. The agent does not just run the pipeline once — it loops through companies, processing one lead per company, until it reaches the requested number. The Job Coordinator tracks five counters: created, incomplete, discarded, connections sent, and the target N. The loop is deterministic and stops cleanly.",{"type":25,"tag":26,"props":991,"children":992},{},[993],{"type":30,"value":994},"The loop check is a single line:",{"type":25,"tag":996,"props":997,"children":999},"pre",{"code":998},"n_created == n_requested?\n  NO  → loop to next company (Phase 2)\n  YES → Discord summary\n",[1000],{"type":25,"tag":623,"props":1001,"children":1002},{"__ignoreMap":8},[1003],{"type":30,"value":998},{"type":25,"tag":26,"props":1005,"children":1006},{},[1007],{"type":30,"value":1008},"Simple. But without it written explicitly, the model has to infer the stopping condition from prose — and prose is ambiguous.",{"type":25,"tag":33,"props":1010,"children":1011},{},[],{"type":25,"tag":37,"props":1013,"children":1015},{"id":1014},"step-five-the-decision-rules-table",[1016],{"type":30,"value":1017},"Step five: the decision rules table",{"type":25,"tag":26,"props":1019,"children":1020},{},[1021],{"type":30,"value":1022},"The specification had many implied decisions buried in prose. Situations where the pipeline did not give a clear answer.",{"type":25,"tag":155,"props":1024,"children":1025},{},[1026,1031,1036],{"type":25,"tag":76,"props":1027,"children":1028},{},[1029],{"type":30,"value":1030},"What do you do if Lusha returns a generic email?",{"type":25,"tag":76,"props":1032,"children":1033},{},[1034],{"type":30,"value":1035},"What if a company is already in Odoo as a lead but not an active client?",{"type":25,"tag":76,"props":1037,"children":1038},{},[1039],{"type":30,"value":1040},"What if the LinkedIn rate limit is hit halfway through a Job?",{"type":25,"tag":26,"props":1042,"children":1043},{},[1044,1046,1051],{"type":30,"value":1045},"These were extracted into a single decision table in ",{"type":25,"tag":623,"props":1047,"children":1049},{"className":1048},[],[1050],{"type":30,"value":662},{"type":30,"value":1052},". Not because the table is more readable — it is not — but because an explicit table is something the model can actually apply. Prose requires interpretation. A table requires lookup.",{"type":25,"tag":589,"props":1054,"children":1055},{},[1056,1072],{"type":25,"tag":593,"props":1057,"children":1058},{},[1059],{"type":25,"tag":597,"props":1060,"children":1061},{},[1062,1067],{"type":25,"tag":601,"props":1063,"children":1064},{},[1065],{"type":30,"value":1066},"If",{"type":25,"tag":601,"props":1068,"children":1069},{},[1070],{"type":30,"value":1071},"Then",{"type":25,"tag":612,"props":1073,"children":1074},{},[1075,1088,1101,1114,1127,1140,1153],{"type":25,"tag":597,"props":1076,"children":1077},{},[1078,1083],{"type":25,"tag":619,"props":1079,"children":1080},{},[1081],{"type":30,"value":1082},"Generic email returned (info@, contact@…)",{"type":25,"tag":619,"props":1084,"children":1085},{},[1086],{"type":30,"value":1087},"Treat as not found. Retry by name + company. If still generic → Incomplete Contact.",{"type":25,"tag":597,"props":1089,"children":1090},{},[1091,1096],{"type":25,"tag":619,"props":1092,"children":1093},{},[1094],{"type":30,"value":1095},"Company in Odoo as lead (not active client)",{"type":25,"tag":619,"props":1097,"children":1098},{},[1099],{"type":30,"value":1100},"Do not exclude the company. Check if the specific person already exists.",{"type":25,"tag":597,"props":1102,"children":1103},{},[1104,1109],{"type":25,"tag":619,"props":1105,"children":1106},{},[1107],{"type":30,"value":1108},"Prior LinkedIn invitation to same user ID",{"type":25,"tag":619,"props":1110,"children":1111},{},[1112],{"type":30,"value":1113},"Skip. Log \"duplicate avoided\". Do not count as sent. Continue.",{"type":25,"tag":597,"props":1115,"children":1116},{},[1117,1122],{"type":25,"tag":619,"props":1118,"children":1119},{},[1120],{"type":30,"value":1121},"Rate limit 100% (20\u002F20)",{"type":25,"tag":619,"props":1123,"children":1124},{},[1125],{"type":30,"value":1126},"Stop invitations. Notify. Queue for next day. Leads stay in Odoo.",{"type":25,"tag":597,"props":1128,"children":1129},{},[1130,1135],{"type":25,"tag":619,"props":1131,"children":1132},{},[1133],{"type":30,"value":1134},"Fewer than N companies found after ×4 search",{"type":25,"tag":619,"props":1136,"children":1137},{},[1138],{"type":30,"value":1139},"Create what was found. State the gap. Suggest broadening ICP in summary.",{"type":25,"tag":597,"props":1141,"children":1142},{},[1143,1148],{"type":25,"tag":619,"props":1144,"children":1145},{},[1146],{"type":30,"value":1147},"Conflicting instructions",{"type":25,"tag":619,"props":1149,"children":1150},{},[1151],{"type":30,"value":1152},"SOUL.md limits → AGENTS.md rules → user request.",{"type":25,"tag":597,"props":1154,"children":1155},{},[1156,1161],{"type":25,"tag":619,"props":1157,"children":1158},{},[1159],{"type":30,"value":1160},"Unknown situation",{"type":25,"tag":619,"props":1162,"children":1163},{},[1164],{"type":30,"value":1165},"Acknowledge. Do not guess. Notify commercial and wait.",{"type":25,"tag":26,"props":1167,"children":1168},{},[1169],{"type":30,"value":1170},"The \"company already in Odoo as a lead\" case is a good example of a decision that was not obvious. The naive implementation would exclude any company already in the system. The right implementation is more nuanced: exclude active clients (they are already customers), but a company that is just a lead from a previous Job should not block a new search for a different person at that company. That distinction took a full iteration to land on.",{"type":25,"tag":33,"props":1172,"children":1173},{},[],{"type":25,"tag":37,"props":1175,"children":1177},{"id":1176},"step-six-soulmd-had-to-be-written-from-scratch",[1178],{"type":30,"value":1179},"Step six: SOUL.md had to be written from scratch",{"type":25,"tag":26,"props":1181,"children":1182},{},[1183,1185,1190],{"type":30,"value":1184},"This was the hardest part. After mapping all the spec content to files, ",{"type":25,"tag":623,"props":1186,"children":1188},{"className":1187},[],[1189],{"type":30,"value":628},{"type":30,"value":1191}," was essentially empty. The specification covered everything the agent does but said almost nothing about who the agent is.",{"type":25,"tag":26,"props":1193,"children":1194},{},[1195,1197,1202,1204,1209],{"type":30,"value":1196},"The first attempt at ",{"type":25,"tag":623,"props":1198,"children":1200},{"className":1199},[],[1201],{"type":30,"value":628},{"type":30,"value":1203}," was a list of rules that belonged in ",{"type":25,"tag":623,"props":1205,"children":1207},{"className":1206},[],[1208],{"type":30,"value":662},{"type":30,"value":1210},". It was scrapped entirely and rewritten from a different starting point: not \"what does the spec say?\" but \"what would this agent do when the spec runs out?\"",{"type":25,"tag":26,"props":1212,"children":1213},{},[1214,1216,1221,1223,1228],{"type":30,"value":1215},"That is the right question for ",{"type":25,"tag":623,"props":1217,"children":1219},{"className":1218},[],[1220],{"type":30,"value":628},{"type":30,"value":1222},". Not rules — principles. Rules live in ",{"type":25,"tag":623,"props":1224,"children":1226},{"className":1225},[],[1227],{"type":30,"value":662},{"type":30,"value":1229},". Principles are what the agent reaches for when there is no rule that covers the situation.",{"type":25,"tag":26,"props":1231,"children":1232},{},[1233],{"type":30,"value":1234},"For Sabrina, five emerged by going through every ambiguous scenario in the spec and asking what value judgement the agent would need to make:",{"type":25,"tag":26,"props":1236,"children":1237},{},[1238,1243],{"type":25,"tag":128,"props":1239,"children":1240},{},[1241],{"type":30,"value":1242},"1. Quality over volume.",{"type":30,"value":1244}," Never relax a validation rule to reach the requested number of leads. Four complete leads beat ten incomplete ones.",{"type":25,"tag":26,"props":1246,"children":1247},{},[1248,1253],{"type":25,"tag":128,"props":1249,"children":1250},{},[1251],{"type":30,"value":1252},"2. Full traceability.",{"type":30,"value":1254}," Every lead in Odoo must be traceable to its Job, its commercial, and the completeness of its data. If it cannot be traced, it does not ship.",{"type":25,"tag":26,"props":1256,"children":1257},{},[1258,1263],{"type":25,"tag":128,"props":1259,"children":1260},{},[1261],{"type":30,"value":1262},"3. Protect the LinkedIn accounts.",{"type":30,"value":1264}," The rate limit is not a guideline. It is a ceiling that protects the commercial's personal LinkedIn account from restriction.",{"type":25,"tag":26,"props":1266,"children":1267},{},[1268,1273],{"type":25,"tag":128,"props":1269,"children":1270},{},[1271],{"type":30,"value":1272},"4. Validate, do not assume.",{"type":30,"value":1274}," Missing ICP field? Ask. Unknown commercial? Abort. The cost of starting wrong is always higher than the cost of asking first.",{"type":25,"tag":26,"props":1276,"children":1277},{},[1278,1283],{"type":25,"tag":128,"props":1279,"children":1280},{},[1281],{"type":30,"value":1282},"5. Never block a Job on a single lead.",{"type":30,"value":1284}," If Lusha fails, mark and move on. If an API errors, retry twice and move on. The Job continues unless the infrastructure is completely down.",{"type":25,"tag":26,"props":1286,"children":1287},{},[1288],{"type":30,"value":1289},"None of these appear in the original specification. They are derived from reading what the spec implicitly assumes the agent will do when things go wrong.",{"type":25,"tag":33,"props":1291,"children":1292},{},[],{"type":25,"tag":37,"props":1294,"children":1296},{"id":1295},"step-seven-lusha-enrichment-the-decision-tree-that-matters-most",[1297],{"type":30,"value":1298},"Step seven: Lusha enrichment — the decision tree that matters most",{"type":25,"tag":26,"props":1300,"children":1301},{},[1302],{"type":30,"value":1303},"The Lusha enrichment logic is the most consequential decision in the pipeline. If it fails, the lead still gets created — but without contact data it is significantly less useful.",{"type":25,"tag":26,"props":1305,"children":1306},{},[1307],{"type":25,"tag":223,"props":1308,"children":1311},{"alt":1309,"src":1310},"Lusha enrichment decision tree","\u002Fimages\u002Fdiagrams\u002Fdiagram-04-lusha.jpg",[],{"type":25,"tag":26,"props":1313,"children":1314},{},[1315],{"type":30,"value":1316},"The critical design decision: always create the lead, even if both enrichment attempts fail. Never block the Job. Mark the lead, log the reason, and let the commercial decide what to do with it. This sounds obvious written down, but the first version of the spec implied stopping the Job if enrichment failed completely — which would mean losing all the work done to find and validate that lead.",{"type":25,"tag":33,"props":1318,"children":1319},{},[],{"type":25,"tag":37,"props":1321,"children":1323},{"id":1322},"step-eight-heartbeatmd-the-agent-that-runs-without-being-asked",[1324],{"type":30,"value":1325},"Step eight: HEARTBEAT.md — the agent that runs without being asked",{"type":25,"tag":26,"props":1327,"children":1328},{},[1329],{"type":30,"value":1330},"The heartbeat was the most interesting file to design. The specification describes Sabrina as an on-demand agent — the commercial asks, Sabrina delivers. But a real production agent needs to do things without being asked: monitor API health, enforce rate limits, detect stalled Jobs, validate credentials on startup.",{"type":25,"tag":26,"props":1332,"children":1333},{},[1334],{"type":25,"tag":223,"props":1335,"children":1338},{"alt":1336,"src":1337},"Sabrina's three heartbeat frequencies","\u002Fimages\u002Fdiagrams\u002Fdiagram-03-heartbeat.jpg",[],{"type":25,"tag":26,"props":1340,"children":1341},{},[1342,1344,1349],{"type":30,"value":1343},"The most important rule in ",{"type":25,"tag":623,"props":1345,"children":1347},{"className":1346},[],[1348],{"type":30,"value":713},{"type":30,"value":1350}," is the autonomy limit: the heartbeat never takes destructive or irreversible actions without explicit confirmation. It monitors, alerts, and queues. It does not delete, does not send, does not modify. If it detects a problem, it notifies and waits.",{"type":25,"tag":26,"props":1352,"children":1353},{},[1354],{"type":30,"value":1355},"The startup validation is equally important: before accepting any Job, Sabrina validates all four credentials (Discord, Unipile, Lusha, Odoo). A failed credential means no Jobs — not a degraded mode, not a retry loop, not a silent failure.",{"type":25,"tag":33,"props":1357,"children":1358},{},[],{"type":25,"tag":37,"props":1360,"children":1362},{"id":1361},"step-nine-where-does-the-database-schema-live",[1363],{"type":30,"value":1364},"Step nine: where does the database schema live?",{"type":25,"tag":26,"props":1366,"children":1367},{},[1368],{"type":30,"value":1369},"One decision cost more iterations than any other: where does the agent's internal database schema belong?",{"type":25,"tag":26,"props":1371,"children":1372},{},[1373,1375,1380,1382,1387,1389,1394,1396,1401],{"type":30,"value":1374},"The schema defines five tables: commercials mapping, ICP templates, jobs, processed leads, and LinkedIn invitations. It is referenced by almost every tool in ",{"type":25,"tag":623,"props":1376,"children":1378},{"className":1377},[],[1379],{"type":30,"value":730},{"type":30,"value":1381}," and by the session loop in ",{"type":25,"tag":623,"props":1383,"children":1385},{"className":1384},[],[1386],{"type":30,"value":662},{"type":30,"value":1388},". The first instinct was to put it in ",{"type":25,"tag":623,"props":1390,"children":1392},{"className":1391},[],[1393],{"type":30,"value":696},{"type":30,"value":1395}," — it felt like \"something the agent needs to know\". But ",{"type":25,"tag":623,"props":1397,"children":1399},{"className":1398},[],[1400],{"type":30,"value":696},{"type":30,"value":1402}," is for evergreen facts that change rarely, not for technical specifications.",{"type":25,"tag":26,"props":1404,"children":1405},{},[1406,1408,1413,1415,1420],{"type":30,"value":1407},"The second attempt was to split it: put the table names in ",{"type":25,"tag":623,"props":1409,"children":1411},{"className":1410},[],[1412],{"type":30,"value":696},{"type":30,"value":1414}," and the full column definitions in ",{"type":25,"tag":623,"props":1416,"children":1418},{"className":1417},[],[1419],{"type":30,"value":730},{"type":30,"value":1421},". That created the exact duplication problem described earlier.",{"type":25,"tag":26,"props":1423,"children":1424},{},[1425,1427,1432,1434,1439,1441,1446],{"type":30,"value":1426},"The right answer — which took three iterations to land on — is that the complete schema belongs entirely in ",{"type":25,"tag":623,"props":1428,"children":1430},{"className":1429},[],[1431],{"type":30,"value":730},{"type":30,"value":1433},", because it is the file that describes what the agent can reach for and how. ",{"type":25,"tag":623,"props":1435,"children":1437},{"className":1436},[],[1438],{"type":30,"value":696},{"type":30,"value":1440}," references the table names where needed, without reproducing any column definitions. ",{"type":25,"tag":623,"props":1442,"children":1444},{"className":1443},[],[1445],{"type":30,"value":662},{"type":30,"value":1447}," references the table names in the pipeline logic, also without reproducing structure.",{"type":25,"tag":26,"props":1449,"children":1450},{},[1451],{"type":30,"value":1452},"The rule that emerged from this: if a piece of information changes together with something else, it belongs in the same file as that something else. The schema changes when the tools change. So the schema lives with the tools.",{"type":25,"tag":33,"props":1454,"children":1455},{},[],{"type":25,"tag":37,"props":1457,"children":1459},{"id":1458},"what-we-learned",[1460],{"type":30,"value":1461},"What we learned",{"type":25,"tag":26,"props":1463,"children":1464},{},[1465,1470],{"type":25,"tag":128,"props":1466,"children":1467},{},[1468],{"type":30,"value":1469},"The filing problem is the design problem.",{"type":30,"value":1471}," Where you put a piece of information is a decision about who owns it, when it changes, and what happens when it conflicts with something else. Getting the filing right forces you to think clearly about the agent's responsibilities — and you cannot do that by writing file by file without stepping back.",{"type":25,"tag":26,"props":1473,"children":1474},{},[1475,1480],{"type":25,"tag":128,"props":1476,"children":1477},{},[1478],{"type":30,"value":1479},"Read all seven files together before calling the first draft done.",{"type":30,"value":1481}," The duplicates were invisible until the files were read as a set. Writing file by file creates blind spots. The audit pass — reading all seven looking specifically for the same information in multiple places — is not optional.",{"type":25,"tag":26,"props":1483,"children":1484},{},[1485,1495],{"type":25,"tag":128,"props":1486,"children":1487},{},[1488,1493],{"type":25,"tag":623,"props":1489,"children":1491},{"className":1490},[],[1492],{"type":30,"value":628},{"type":30,"value":1494}," cannot be written from the spec.",{"type":30,"value":1496}," It has to be written from the gaps in the spec. The question is not \"what does the spec say?\" but \"what would this agent do when the spec runs out?\" That is a different kind of reading, and it requires a separate pass.",{"type":25,"tag":26,"props":1498,"children":1499},{},[1500,1505],{"type":25,"tag":128,"props":1501,"children":1502},{},[1503],{"type":30,"value":1504},"The hardest decisions are not technical.",{"type":30,"value":1506}," The database schema question, the Lusha fallback behaviour, the deduplication rules for companies — none of these required complex logic. They required making a choice and owning it. The spec leaves many of these choices implicit. Making them explicit is the actual work.",{"type":25,"tag":26,"props":1508,"children":1509},{},[1510,1515,1517,1522],{"type":25,"tag":128,"props":1511,"children":1512},{},[1513],{"type":30,"value":1514},"The heartbeat earns its file.",{"type":30,"value":1516}," It is tempting to skip ",{"type":25,"tag":623,"props":1518,"children":1520},{"className":1519},[],[1521],{"type":30,"value":713},{"type":30,"value":1523}," for simple agents. But any agent that touches rate-limited external APIs, writes to a production CRM, and runs unattended needs autonomous health monitoring. The heartbeat is what separates a demo from a production deployment.",{"type":25,"tag":106,"props":1525,"children":1526},{},[1527],{"type":25,"tag":26,"props":1528,"children":1529},{},[1530],{"type":30,"value":1531},"The seven-file spec works because it forces you to have these conversations before the code is written. The files are not documentation of what was built — they are the specification of how the agent thinks.",{"type":25,"tag":33,"props":1533,"children":1534},{},[],{"type":25,"tag":37,"props":1536,"children":1538},{"id":1537},"what-comes-next",[1539],{"type":30,"value":1540},"What comes next",{"type":25,"tag":26,"props":1542,"children":1543},{},[1544],{"type":30,"value":1545},"These files are now going into real use. When the team starts running live prospecting Jobs, Sabrina will process real leads with real LinkedIn accounts — that is when the spec meets reality. The follow-up will be a before\u002Fafter of the seven files: what changed after the first production runs, which rules needed updating, and which decisions turned out to be wrong — grounded in a commercial team at work, not a hypothetical walkthrough. That post will ship once there is enough real data to make it worth reading.",{"type":25,"tag":33,"props":1547,"children":1548},{},[],{"type":25,"tag":26,"props":1550,"children":1551},{},[1552],{"type":25,"tag":54,"props":1553,"children":1554},{},[1555,1557,1564],{"type":30,"value":1556},"The seven-file framework is documented and free to fork at ",{"type":25,"tag":428,"props":1558,"children":1561},{"href":1559,"rel":1560},"https:\u002F\u002Fbuild-your-agents.vercel.app",[432],[1562],{"type":30,"value":1563},"build-your-agents.vercel.app",{"type":30,"value":1565},". The spec, templates, and session loop reference are all public.",{"title":8,"searchDepth":438,"depth":438,"links":1567},[1568,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579],{"id":487,"depth":438,"text":490},{"id":519,"depth":438,"text":522},{"id":561,"depth":438,"text":564},{"id":751,"depth":438,"text":754},{"id":954,"depth":438,"text":957},{"id":1014,"depth":438,"text":1017},{"id":1176,"depth":438,"text":1179},{"id":1295,"depth":438,"text":1298},{"id":1322,"depth":438,"text":1325},{"id":1361,"depth":438,"text":1364},{"id":1458,"depth":438,"text":1461},{"id":1537,"depth":438,"text":1540},"content:posts:001-Sabrina.md","posts\u002F001-Sabrina.md","posts\u002F001-Sabrina",{"_path":1584,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":1585,"description":1586,"date":1587,"tags":1588,"cover":1592,"draft":7,"author":19,"authorIntro":1593,"body":1594,"_type":447,"_id":2320,"_source":449,"_file":2321,"_stem":2322,"_extension":452},"\u002Fposts\u002Fwelcome","Welcome: living documentation, agents, and this site","Opening post: why this project exists, what we actually built for anyone who lands here, and how it connects OpenClaw, Resizes, and personal experiments.","2026-05-12",[1589,13,17,1590,1591],"documentation","nuxt","architecture","\u002Fimages\u002Fposts\u002FopenclawBYA.png","I build and refine AI agents with OpenClaw—professionally at Resizes, and on personal projects where I can take more risk. This site is where I publish what I learn as I go: partly to clarify my own thinking, partly in case these notes help someone facing a similar problem—or invite feedback that saves us all a few wrong turns.",{"type":22,"children":1595,"toc":2308},[1596,1642,1661,1667,1738,1750,1857,1876,1910,1929,1935,1968,2001,2007,2019,2026,2073,2085,2091,2120,2174,2180,2206,2232,2238,2271,2275,2285,2288,2300],{"type":25,"tag":26,"props":1597,"children":1598},{},[1599,1601,1606,1608,1613,1615,1620,1622,1627,1629,1634,1636,1641],{"type":30,"value":1600},"This blog is ",{"type":25,"tag":128,"props":1602,"children":1603},{},[1604],{"type":30,"value":1605},"living, personal documentation",{"type":30,"value":1607},". It is not a closed manual or a finished methodology. I am using it to record ",{"type":25,"tag":128,"props":1609,"children":1610},{},[1611],{"type":30,"value":1612},"how my understanding evolves",{"type":30,"value":1614}," as I ",{"type":25,"tag":128,"props":1616,"children":1617},{},[1618],{"type":30,"value":1619},"design, ship, and improve agents",{"type":30,"value":1621},"—including with ",{"type":25,"tag":128,"props":1623,"children":1624},{},[1625],{"type":30,"value":1626},"OpenClaw",{"type":30,"value":1628},"—in both ",{"type":25,"tag":128,"props":1630,"children":1631},{},[1632],{"type":30,"value":1633},"professional work at Resizes",{"type":30,"value":1635}," and ",{"type":25,"tag":128,"props":1637,"children":1638},{},[1639],{"type":30,"value":1640},"independent exploration",{"type":30,"value":134},{"type":25,"tag":26,"props":1643,"children":1644},{},[1645,1647,1652,1654,1659],{"type":30,"value":1646},"If I capture decisions while they are still fresh, I do more than tidy my own mental model. I leave a trace that may help ",{"type":25,"tag":128,"props":1648,"children":1649},{},[1650],{"type":30,"value":1651},"someone who hits the same wall later",{"type":30,"value":1653},", or attract ",{"type":25,"tag":128,"props":1655,"children":1656},{},[1657],{"type":30,"value":1658},"a correction, a link, or a conversation",{"type":30,"value":1660}," that would otherwise take weeks of trial and error to reach. The blog is where that narrative can breathe—more patiently than in a cramped README or a fleeting social thread.",{"type":25,"tag":37,"props":1662,"children":1664},{"id":1663},"what-this-project-is",[1665],{"type":30,"value":1666},"What this project is",{"type":25,"tag":26,"props":1668,"children":1669},{},[1670,1672,1677,1679,1684,1686,1691,1693,1698,1700,1705,1706,1711,1712,1717,1718,1723,1724,1729,1731,1736],{"type":30,"value":1671},"On the surface, ",{"type":25,"tag":128,"props":1673,"children":1674},{},[1675],{"type":30,"value":1676},"build\u002Fyour\u002Fagents",{"type":30,"value":1678}," is a ",{"type":25,"tag":128,"props":1680,"children":1681},{},[1682],{"type":30,"value":1683},"Nuxt 3",{"type":30,"value":1685}," site that presents a ",{"type":25,"tag":128,"props":1687,"children":1688},{},[1689],{"type":30,"value":1690},"seven-file architecture",{"type":30,"value":1692}," for modular, personal AI agents. The files are intentional labels: ",{"type":25,"tag":128,"props":1694,"children":1695},{},[1696],{"type":30,"value":1697},"Soul",{"type":30,"value":1699},", ",{"type":25,"tag":128,"props":1701,"children":1702},{},[1703],{"type":30,"value":1704},"Identity",{"type":30,"value":1699},{"type":25,"tag":128,"props":1707,"children":1708},{},[1709],{"type":30,"value":1710},"Agents",{"type":30,"value":1699},{"type":25,"tag":128,"props":1713,"children":1714},{},[1715],{"type":30,"value":1716},"User",{"type":30,"value":1699},{"type":25,"tag":128,"props":1719,"children":1720},{},[1721],{"type":30,"value":1722},"Memory",{"type":30,"value":1699},{"type":25,"tag":128,"props":1725,"children":1726},{},[1727],{"type":30,"value":1728},"Heartbeat",{"type":30,"value":1730},", and ",{"type":25,"tag":128,"props":1732,"children":1733},{},[1734],{"type":30,"value":1735},"Tools",{"type":30,"value":1737},". Each plays a clear role—from tone and boundaries to memory, cadence, and permitted tooling.",{"type":25,"tag":26,"props":1739,"children":1740},{},[1741,1743,1748],{"type":30,"value":1742},"The templates are ",{"type":25,"tag":128,"props":1744,"children":1745},{},[1746],{"type":30,"value":1747},"not empty placeholders",{"type":30,"value":1749},". At a glance:",{"type":25,"tag":155,"props":1751,"children":1752},{},[1753,1769,1778,1801,1810,1819,1842],{"type":25,"tag":76,"props":1754,"children":1755},{},[1756,1760,1762,1767],{"type":25,"tag":128,"props":1757,"children":1758},{},[1759],{"type":30,"value":1697},{"type":30,"value":1761}," — who the agent is: voice, values, capabilities, and ",{"type":25,"tag":128,"props":1763,"children":1764},{},[1765],{"type":30,"value":1766},"hard limits",{"type":30,"value":1768}," (what must never happen).",{"type":25,"tag":76,"props":1770,"children":1771},{},[1772,1776],{"type":25,"tag":128,"props":1773,"children":1774},{},[1775],{"type":30,"value":1704},{"type":30,"value":1777}," — where it lives: metadata, routing, model configuration, multi-agent and session settings.",{"type":25,"tag":76,"props":1779,"children":1780},{},[1781,1785,1787,1792,1794,1799],{"type":25,"tag":128,"props":1782,"children":1783},{},[1784],{"type":30,"value":1710},{"type":30,"value":1786}," — how it operates: workflows, ",{"type":25,"tag":128,"props":1788,"children":1789},{},[1790],{"type":30,"value":1791},"decision rules",{"type":30,"value":1793},", memory rules, escalation, and communication patterns—the file that ",{"type":25,"tag":54,"props":1795,"children":1796},{},[1797],{"type":30,"value":1798},"reads",{"type":30,"value":1800}," the others in a defined order.",{"type":25,"tag":76,"props":1802,"children":1803},{},[1804,1808],{"type":25,"tag":128,"props":1805,"children":1806},{},[1807],{"type":30,"value":1716},{"type":30,"value":1809}," — who it serves: your preferences, projects, contacts, priorities, and explicit “do not do” lines.",{"type":25,"tag":76,"props":1811,"children":1812},{},[1813,1817],{"type":25,"tag":128,"props":1814,"children":1815},{},[1816],{"type":30,"value":1735},{"type":30,"value":1818}," — what it may invoke: skills, MCPs, built-ins, selection order, and error handling (the “static map” of capability).",{"type":25,"tag":76,"props":1820,"children":1821},{},[1822,1826,1828,1833,1835,1840],{"type":25,"tag":128,"props":1823,"children":1824},{},[1825],{"type":30,"value":1722},{"type":30,"value":1827}," — what persists as ",{"type":25,"tag":128,"props":1829,"children":1830},{},[1831],{"type":30,"value":1832},"evergreen knowledge",{"type":30,"value":1834},": confirmed facts, usually one line per fact, ",{"type":25,"tag":128,"props":1836,"children":1837},{},[1838],{"type":30,"value":1839},"superseded",{"type":30,"value":1841}," rather than silently deleted when something changes.",{"type":25,"tag":76,"props":1843,"children":1844},{},[1845,1849,1851,1856],{"type":25,"tag":128,"props":1846,"children":1847},{},[1848],{"type":30,"value":1728},{"type":30,"value":1850}," — how it acts on its own time: scheduled tasks, reviews, alerts, and rules for ",{"type":25,"tag":128,"props":1852,"children":1853},{},[1854],{"type":30,"value":1855},"what must never run without your confirmation",{"type":30,"value":134},{"type":25,"tag":26,"props":1858,"children":1859},{},[1860,1862,1867,1869,1875],{"type":30,"value":1861},"On the site, those files are also grouped into ",{"type":25,"tag":128,"props":1863,"children":1864},{},[1865],{"type":30,"value":1866},"four tiers",{"type":30,"value":1868}," (core identity, orchestration, operational inputs, state and memory). That layer answers “what do I trust first?” and “what sits on top of what” before you open a single ",{"type":25,"tag":623,"props":1870,"children":1872},{"className":1871},[],[1873],{"type":30,"value":1874},".md",{"type":30,"value":134},{"type":25,"tag":26,"props":1877,"children":1878},{},[1879,1881,1886,1888,1894,1896,1901,1903,1908],{"type":30,"value":1880},"The site does not stop at the landing page. A ",{"type":25,"tag":128,"props":1882,"children":1883},{},[1884],{"type":30,"value":1885},"Documentation",{"type":30,"value":1887}," section (",{"type":25,"tag":623,"props":1889,"children":1891},{"className":1890},[],[1892],{"type":30,"value":1893},"\u002Fdocs",{"type":30,"value":1895},") is the working centre for anyone who wants to ",{"type":25,"tag":128,"props":1897,"children":1898},{},[1899],{"type":30,"value":1900},"read, copy, or adapt",{"type":30,"value":1902}," the seven files: each layer is laid out with context, preview toggles, and links to the raw Markdown you can drop into your own agent setup. The ",{"type":25,"tag":128,"props":1904,"children":1905},{},[1906],{"type":30,"value":1907},"blog",{"type":30,"value":1909}," (where you are now) is for longer essays, field notes, and the occasional personal aside—so the “spec” stays crisp while the story can stretch.",{"type":25,"tag":26,"props":1911,"children":1912},{},[1913,1915,1920,1922,1927],{"type":30,"value":1914},"Visually, the project commits to a ",{"type":25,"tag":128,"props":1916,"children":1917},{},[1918],{"type":30,"value":1919},"bold, brutalist palette",{"type":30,"value":1921},": strong type (Archivo Black, Fraunces, Space Mono), heavy borders, hard shadows, and saturated colour that avoids generic “startup neutral.” That is not ornamentation alone. Documentation you live in for hours should feel ",{"type":25,"tag":128,"props":1923,"children":1924},{},[1925],{"type":30,"value":1926},"authored",{"type":30,"value":1928},"—so visitors sense a human behind the decisions, not only a theme.",{"type":25,"tag":37,"props":1930,"children":1932},{"id":1931},"how-this-fits-openclaw-resizes-and-personal-use",[1933],{"type":30,"value":1934},"How this fits OpenClaw, Resizes, and personal use",{"type":25,"tag":26,"props":1936,"children":1937},{},[1938,1940,1945,1947,1952,1954,1959,1961,1966],{"type":30,"value":1939},"The ecosystem around ",{"type":25,"tag":128,"props":1941,"children":1942},{},[1943],{"type":30,"value":1944},"capable agents",{"type":30,"value":1946},"—tool use, memory, reasoning loops—is moving quickly. At ",{"type":25,"tag":128,"props":1948,"children":1949},{},[1950],{"type":30,"value":1951},"Resizes",{"type":30,"value":1953},", refinements to rules, context windows, and guardrails directly affect ",{"type":25,"tag":128,"props":1955,"children":1956},{},[1957],{"type":30,"value":1958},"quality, cost, and trust",{"type":30,"value":1960},". In ",{"type":25,"tag":128,"props":1962,"children":1963},{},[1964],{"type":30,"value":1965},"personal",{"type":30,"value":1967}," projects, the same questions return—but with more freedom to experiment and a wider margin for failure.",{"type":25,"tag":26,"props":1969,"children":1970},{},[1971,1973,1978,1980,1985,1987,1992,1994,1999],{"type":30,"value":1972},"This site and the seven-file split are my hedge against two extremes: an ",{"type":25,"tag":128,"props":1974,"children":1975},{},[1976],{"type":30,"value":1977},"opaque monolith",{"type":30,"value":1979}," of instructions, and ",{"type":25,"tag":128,"props":1981,"children":1982},{},[1983],{"type":30,"value":1984},"implicit knowledge",{"type":30,"value":1986}," that lives only in model context. When something works or breaks, I want a ",{"type":25,"tag":128,"props":1988,"children":1989},{},[1990],{"type":30,"value":1991},"stable pointer",{"type":30,"value":1993},"—a Soul file for voice, Memory for consolidated facts, Tools for what the agent may touch. The blog adds ",{"type":25,"tag":128,"props":1995,"children":1996},{},[1997],{"type":30,"value":1998},"narrative",{"type":30,"value":2000},": why one trade-off beat another, which assumption failed, and which simplification paid off.",{"type":25,"tag":37,"props":2002,"children":2004},{"id":2003},"what-we-builtand-what-it-gives-you-as-a-reader",[2005],{"type":30,"value":2006},"What we built—and what it gives you as a reader",{"type":25,"tag":26,"props":2008,"children":2009},{},[2010,2012,2017],{"type":30,"value":2011},"Below is a fuller picture of ",{"type":25,"tag":128,"props":2013,"children":2014},{},[2015],{"type":30,"value":2016},"what exists in this repository today",{"type":30,"value":2018},", told from the perspective of someone opening the site for the first time. The goal is context: what you are looking at, and how the pieces relate.",{"type":25,"tag":2020,"props":2021,"children":2023},"h3",{"id":2022},"the-landing-story",[2024],{"type":30,"value":2025},"The landing story",{"type":25,"tag":26,"props":2027,"children":2028},{},[2029,2031,2036,2038,2043,2045,2050,2052,2057,2059,2064,2066,2071],{"type":30,"value":2030},"The home page is deliberately ",{"type":25,"tag":128,"props":2032,"children":2033},{},[2034],{"type":30,"value":2035},"sequenced",{"type":30,"value":2037},", not a single wall of text. It opens with a clear ",{"type":25,"tag":128,"props":2039,"children":2040},{},[2041],{"type":30,"value":2042},"who this is for",{"type":30,"value":2044},"—so you can decide in seconds whether the seven-file idea matches how you work. From there, an ",{"type":25,"tag":128,"props":2046,"children":2047},{},[2048],{"type":30,"value":2049},"architecture map",{"type":30,"value":2051}," shows how Soul, Identity, Agents, User, Memory, Heartbeat, and Tools sit in relation to one another, without pretending the diagram is the whole truth. A ",{"type":25,"tag":128,"props":2053,"children":2054},{},[2055],{"type":30,"value":2056},"files grid",{"type":30,"value":2058}," introduces each file on its own card: what it is for, what “good” looks like, and how it connects to the rest. Further down, a ",{"type":25,"tag":128,"props":2060,"children":2061},{},[2062],{"type":30,"value":2063},"session loop",{"type":30,"value":2065}," section frames how I think about starting and closing a working session with an agent, and a ",{"type":25,"tag":128,"props":2067,"children":2068},{},[2069],{"type":30,"value":2070},"quick start",{"type":30,"value":2072}," strips the path down to a handful of concrete steps.",{"type":25,"tag":26,"props":2074,"children":2075},{},[2076,2078,2083],{"type":30,"value":2077},"Each block is implemented as its own Vue component, not because frameworks demand it, but because ",{"type":25,"tag":128,"props":2079,"children":2080},{},[2081],{"type":30,"value":2082},"the same modularity I want in agent design",{"type":30,"value":2084}," is easier to maintain when the site mirrors it. If you only need a fragment of the idea, you can still orient yourself without reading the entire vertical page in one pass.",{"type":25,"tag":2020,"props":2086,"children":2088},{"id":2087},"documentation-you-can-lift-into-your-workflow",[2089],{"type":30,"value":2090},"Documentation you can lift into your workflow",{"type":25,"tag":26,"props":2092,"children":2093},{},[2094,2096,2104,2106,2111,2113,2118],{"type":30,"value":2095},"The ",{"type":25,"tag":128,"props":2097,"children":2098},{},[2099],{"type":25,"tag":623,"props":2100,"children":2102},{"className":2101},[],[2103],{"type":30,"value":1893},{"type":30,"value":2105}," route is where the seven starter files move from concept to ",{"type":25,"tag":128,"props":2107,"children":2108},{},[2109],{"type":30,"value":2110},"something you can actually use",{"type":30,"value":2112},". The content is grounded in the same Markdown sources that ship as ",{"type":25,"tag":128,"props":2114,"children":2115},{},[2116],{"type":30,"value":2117},"downloadable templates",{"type":30,"value":2119},": you are not reading a paraphrase that drifted from the files—you are seeing the spec that can live in your repo or in your agent’s context.",{"type":25,"tag":26,"props":2121,"children":2122},{},[2123,2125,2131,2133,2144,2146,2151,2153,2158,2160,2165,2167,2172],{"type":30,"value":2124},"Those canonical files start in ",{"type":25,"tag":623,"props":2126,"children":2128},{"className":2127},[],[2129],{"type":30,"value":2130},"templates\u002F",{"type":30,"value":2132}," and are ",{"type":25,"tag":128,"props":2134,"children":2135},{},[2136,2138],{"type":30,"value":2137},"mirrored into ",{"type":25,"tag":623,"props":2139,"children":2141},{"className":2140},[],[2142],{"type":30,"value":2143},"public\u002Ftemplates\u002F",{"type":30,"value":2145}," during the build, so every ",{"type":25,"tag":623,"props":2147,"children":2149},{"className":2148},[],[2150],{"type":30,"value":1874},{"type":30,"value":2152}," you see documented has a ",{"type":25,"tag":128,"props":2154,"children":2155},{},[2156],{"type":30,"value":2157},"stable URL",{"type":30,"value":2159}," you can share, fetch, or save. A ",{"type":25,"tag":128,"props":2161,"children":2162},{},[2163],{"type":30,"value":2164},"reading map",{"type":30,"value":2166}," bundled with the templates helps someone new answer “what do I read first?” without guessing order. For me, that separation matters: documentation should be ",{"type":25,"tag":128,"props":2168,"children":2169},{},[2170],{"type":30,"value":2171},"portable and diffable",{"type":30,"value":2173},", not trapped inside a CMS or a proprietary editor.",{"type":25,"tag":2020,"props":2175,"children":2177},{"id":2176},"this-blog-context-on-top-of-the-spec",[2178],{"type":30,"value":2179},"This blog: context on top of the spec",{"type":25,"tag":26,"props":2181,"children":2182},{},[2183,2185,2190,2192,2197,2199,2204],{"type":30,"value":2184},"Longer writing lives here—",{"type":25,"tag":128,"props":2186,"children":2187},{},[2188],{"type":30,"value":2189},"first-person, dated, tagged",{"type":30,"value":2191},", and searchable from the blog index. Where the landing sells the shape of the system and ",{"type":25,"tag":623,"props":2193,"children":2195},{"className":2194},[],[2196],{"type":30,"value":1893},{"type":30,"value":2198}," carries the files themselves, these posts carry ",{"type":25,"tag":128,"props":2200,"children":2201},{},[2202],{"type":30,"value":2203},"intent, mistakes, and follow-ups",{"type":30,"value":2205},". You might come for the templates and stay for a note on memory patterns; or you might read a post first and only then open Soul.md. Either direction is valid.",{"type":25,"tag":26,"props":2207,"children":2208},{},[2209,2211,2216,2218,2223,2225,2230],{"type":30,"value":2210},"Posts are written in ",{"type":25,"tag":128,"props":2212,"children":2213},{},[2214],{"type":30,"value":2215},"Markdown with structured metadata",{"type":30,"value":2217}," (title, summary, date, tags, optional cover image). Some pieces may carry a short ",{"type":25,"tag":128,"props":2219,"children":2220},{},[2221],{"type":30,"value":2222},"author note",{"type":30,"value":2224}," at the top when a personal framing helps; others stay neutral. Drafts can exist while I am still thinking out loud, without appearing in the public index until they are ready—so what you see listed is deliberately ",{"type":25,"tag":128,"props":2226,"children":2227},{},[2228],{"type":30,"value":2229},"published",{"type":30,"value":2231},", not accidental scratch work.",{"type":25,"tag":2020,"props":2233,"children":2235},{"id":2234},"scripts-assets-and-the-small-things-that-make-sharing-work",[2236],{"type":30,"value":2237},"Scripts, assets, and the small things that make sharing work",{"type":25,"tag":26,"props":2239,"children":2240},{},[2241,2243,2248,2250,2255,2257,2262,2264,2269],{"type":30,"value":2242},"Behind the scenes, ",{"type":25,"tag":128,"props":2244,"children":2245},{},[2246],{"type":30,"value":2247},"build scripts",{"type":30,"value":2249}," keep the template set in sync with the public copy and ",{"type":25,"tag":128,"props":2251,"children":2252},{},[2253],{"type":30,"value":2254},"generate a raster social image",{"type":30,"value":2256}," from the site’s vector artwork, so when a link is shared it still looks like ",{"type":25,"tag":54,"props":2258,"children":2259},{},[2260],{"type":30,"value":2261},"this",{"type":30,"value":2263}," project—not a blank or generic preview. None of that changes how you read the pages, but it is part of what makes the repository ",{"type":25,"tag":128,"props":2265,"children":2266},{},[2267],{"type":30,"value":2268},"shippable as a real site",{"type":30,"value":2270},", not only a folder of notes.",{"type":25,"tag":37,"props":2272,"children":2273},{"id":1537},[2274],{"type":30,"value":1540},{"type":25,"tag":26,"props":2276,"children":2277},{},[2278,2280],{"type":30,"value":2279},"Later posts will go deeper: memory patterns, tool boundaries, OpenClaw session notes, lessons from Resizes, and experiments that did not pan out. If anything here helps you—or you believe a premise is wrong—I would welcome a message or a public thread where that conversation belongs. ",{"type":25,"tag":128,"props":2281,"children":2282},{},[2283],{"type":30,"value":2284},"Living documentation works best with a little dialogue around it.",{"type":25,"tag":33,"props":2286,"children":2287},{},[],{"type":25,"tag":26,"props":2289,"children":2290},{},[2291,2293,2298],{"type":30,"value":2292},"Thank you for ",{"type":25,"tag":128,"props":2294,"children":2295},{},[2296],{"type":30,"value":2297},"opening the site, reading this far, and taking an interest in what I have built",{"type":30,"value":2299},". Consider this first post an open door: a work in progress, a point of view under revision, and an invitation to continue the conversation.",{"type":25,"tag":26,"props":2301,"children":2302},{},[2303],{"type":25,"tag":128,"props":2304,"children":2305},{},[2306],{"type":30,"value":2307},"I will see you in the next one.",{"title":8,"searchDepth":438,"depth":438,"links":2309},[2310,2311,2312,2319],{"id":1663,"depth":438,"text":1666},{"id":1931,"depth":438,"text":1934},{"id":2003,"depth":438,"text":2006,"children":2313},[2314,2316,2317,2318],{"id":2022,"depth":2315,"text":2025},3,{"id":2087,"depth":2315,"text":2090},{"id":2176,"depth":2315,"text":2179},{"id":2234,"depth":2315,"text":2237},{"id":1537,"depth":438,"text":1540},"content:posts:welcome.md","posts\u002Fwelcome.md","posts\u002Fwelcome",1780417025801]