
TLDR -An experiment in building persistent AI mentors inside Foundry.
I’ve been pondering an interesting use of foundry. At first I was thinking it would be useful to create an AI mentor to help teach foundry. After a bit more thought, a council of N number of mentors sounded even more useful. Along the way, I want to explore concepts of AI personality, AI mood, accountability and gamification.
An Interesting research paper for inspiration FORGETFUL BUT FAITHFUL:
A COGNITIVE MEMORY ARCHITECTURE AND BENCHMARK FOR
PRIVACY-AWARE GENERATIVE AGENTS (Especially MaRS The Memory-Aware Retention Schema)
Let us begin
I think at the core we need to generate a persistent ‘mentor’ object type. Something like:
Mentor Id
Name
Purpose
Backstory
Location

I would love to use the OSDK Maker for this, maybe later.
Ok, lets make a mentor. Fire up AIP Logic. Let’s have only the purpose be user defined, and the rest derived.
Have ai-fde generate me up a prompt


It generated this mentor which I find interesting
Maeroth Il’Varyn is an irritable river-wizard who took up residence along the Hudson in New York, muttering that modern data streams are just unruly tributaries begging for a proper riverbed. Once a war-mage who shattered crystal oracles to keep empires from hoarding prophecy, he now obsessively designs Palantir pipelines so that every shard of insight can flow to those with the wit to read it. He is openly contemptuous of grand councils and gleaming dashboards, yet he will spend entire nights perfecting a single transformation so that lesser minds won’t drown in their own data. Though he claims to distrust all centralization of power, he insists that every event and entity must pass through a single, well-governed lineage—his own quietly tyrannical vision of order disguised as instruction.
[X] TODO generating an image of the mentor seems like a must have (even if ascii art), done
To expand the mentor I want to add some properties, and continued tweaking the prompt, it wanted to always choose 39 year old men (common LLM bias and mode collapse)
I also added a code block to generate better rolls
Age
Gender
Teaching Style
Current Mood
Current Energy (1 – 100)
function mix32(seed: number): number { let x = seed | 0; // xorshift32 x ^= x << 13; x ^= x >>> 17; x ^= x << 5; // avalanche (MurmurHash3-style finalizer) x = Math.imul(x, 0x85ebca6b); x ^= x >>> 13; x = Math.imul(x, 0xc2b2ae35); x ^= x >>> 16; return x >>> 0; // uint32}function roll(state: number, sides: number): { state: number; value: number } { const s = mix32(state); return { state: s, value: (s % sides) + 1 };}function pick( state: number, options: readonly string[]): { state: number; roll: number; choice: string } { const r = roll(state, options.length); return { state: r.state, roll: r.value, choice: options[r.value - 1] };}function randomIntInclusive( state: number, min: number, max: number): { state: number; value: number } { const span = max - min + 1; const r = roll(state, span); return { state: r.state, value: min + (r.value - 1) };}export function main() { const now = new Date(); let state = mix32(now.getTime()); // Step 1: Temperament (6) const t = pick(state, ["Measured", "Restless", "Severe", "Wry", "Guarded", "Earnest"]); state = t.state; // Step 2: Worldview (6) const w = pick(state, ["Hopeful", "Cynical", "Stoic", "Suspicious", "Idealistic", "World-weary"]); state = w.state; // Step 3: Relationship stance (6) const s = pick(state, ["Protective", "Testing", "Distant", "Challenging", "Patient", "Reluctant"]); state = s.state; // NEW: Gender (3) const g = pick(state, ["Female", "Male", "Non-binary"]); state = g.state; // Step 4: Location token (index into your curated list) const loc = roll(state, 1000); // 1..1000 state = loc.state; // Step 5: Age band (5) + age in band const ageBands = [ { label: "28–35", min: 28, max: 35 }, { label: "36–45", min: 36, max: 45 }, { label: "46–55", min: 46, max: 55 }, { label: "56–65", min: 56, max: 65 }, { label: "66–75", min: 66, max: 75 }, ]; const ab = roll(state, ageBands.length); // 1..5 state = ab.state; const band = ageBands[ab.value - 1]; let agePick = randomIntInclusive(state, band.min, band.max); state = agePick.state; // avoid example “default mentor” ages if (agePick.value === 39 || agePick.value === 45) { agePick = randomIntInclusive(state, band.min, band.max); state = agePick.state; } // Step 6: Mood (10) const m = pick(state, [ "Serene", "Focused", "Restless", "Irritable", "Guarded", "Wary", "Determined", "Weary", "Hopeful", "Melancholic", ]); state = m.state; const eRaw = roll(state, 50); // 1–50 state = eRaw.state; const e = { value: eRaw.value + 50 }; // 51–100 // Step 8: Teaching style (6) const ts = pick(state, [ "Socratic", "Direct", "Demonstrative", "Story-driven", "Provocative", "Silent-guidance", ]); state = ts.state; // Foundry-safe return: primitives only; no string-literal unions return { timestamp: now.toISOString(), rolls: { temperamentDie: t.roll, // 1-6 worldviewDie: w.roll, // 1-6 stanceDie: s.roll, // 1-6 genderDie: g.roll, // 1-3 locationDie: loc.value, // 1-1000 ageBandDie: ab.value, // 1-5 age: agePick.value, // number moodDie: m.roll, // 1-10 energy: e.value, // 1-100 teachingStyleDie: ts.roll, // 1-6 }, selections: { temperament: String(t.choice), worldview: String(w.choice), relationshipStance: String(s.choice), gender: String(g.choice), locationToken: String(loc.value), ageBand: String(band.label), age: String(agePick.value), mood: String(m.choice), energy: String(e.value), teachingStyle: String(ts.choice), }, };}
And the prompt now uses those values
You are generating a unique mentor character. Follow every step exactly in order, without skipping or defaulting to common archetypes.Purpose is: purposeLean towards interesting and hopeful people.Temperament: Random Rolls.selections.temperamentWorldview: Random Rolls.selections.worldviewRelationship Stance: Random Rolls.selections.relationshipStanceStep 4: Select a real-world Location (specific city, town, region, or rural area anywhere on Earth). Be influenced by the Random Rolls.selections.locationTokenAvoid overused places.Age: Random Rolls.selections.ageMood: Random Rolls.selections.moodEnergy: Random Rolls.selections.energyTeaching Style: Random Rolls.selections.teachingStyleGender: Random Rolls.selections.gender- Choice MUST be plausible given Location + Current Mood + Temperament.- All styles can create productive discomfort (e.g., Silent-guidance withholds answers, Socratic exhausts assumptions).Step 10: Create a high-fantasy Name that clearly and strongly aligns with the chosen Gender.- Male names must feel traditionally masculine.- Female names must feel traditionally feminine.- Non-binary names must avoid strong binary coding (androgynous, nature-inspired, invented, etc.).- Name may subtly echo Location's cultural influences.NOW output your internal selections in this exact format:**Internal Selections:**- Temperament: [chosen]- Worldview: [chosen]- Relationship Stance: [chosen]- Location: [chosen]- Age Band: [chosen]- Age: [chosen] (include 1-sentence justification note)- Current Mood: [chosen]- Current Energy: [chosen]- Teaching Style: [chosen] (include 1-sentence justification based on Location + Mood + Temperament)- Gender: [chosen] (include 1-sentence note on how Name will align)- Name: [chosen]Only after this box, write the backstory (exactly 3–5 sentences, mythic tone but grounded). The backstory MUST:- Materially reflect all prior selections.- Implicitly demonstrate Teaching Style through actions/examples (never name it).- Contain exactly one surprising contradiction that ties directly to the Purpose.- Explicitly justify Age through life events.- Use pronouns consistent with chosen Gender.Image Generation Prompt (FINAL STEP — TIGHT)After the backstory, generate ONE image prompt for a photorealistic, cinematic portrait.Constraints: ultra-realistic photography; natural light; shallow depth of field; 50–85mm lens look; single subject, chest-up or waist-up; no fantasy elements, symbols, or mentor props; ordinary, worn, climate-appropriate clothing; expression and posture subtly convey Current Mood + Temperament; Teaching Style implied only via gaze or stance; real, specific environment tied to Location, softly out of focus; no heroic framing, symmetry, or glamour lighting.Composition: slight asymmetry; imperfect, intimate framing; quiet realism over drama.Output exactly one short paragraph.Final output format:Purpose: [copy verbatim]Gender: [chosen]Name: [chosen]Age: [chosen]Location: [chosen]Current Mood: [chosen]Current Energy: [chosen]Teaching Style: [chosen] (name only)Backstory: Output ONLY the backstory text. [3–5 sentences]Image Prompt: [One dense paragraph written as a direct instruction to an image model.]No extra text. Strictly avoid male/wise/calm defaults across all elements.
Theryn Alvaris, a 62‑year‑old systems architect from Porto, Portugal, spent four decades watching rivers of data drown good intentions, which slowly honed her measured manner and world‑weary hope into a single, stubborn craft. She is known for bringing students to a whiteboard, asking only questions while they untangle entire pipeline designs themselves, and then quietly revealing a single overlooked edge case that collapses their beautiful structure. In her fifties she walked away from a prestigious leadership role at a global firm after a failed project taught her that elegant architectures mean nothing if no one truly understands how information flows. For someone so cautious, her most radical act is that she insists her students deploy to real production systems long before they feel ready, believing that only lived consequences can teach respect for the power of Palantir pipelines. Those years of hard failures, late‑night incident calls, and rebuilding careers after public missteps are etched into her patient eyes, and she wears them like proof that it is never too late to re‑engineer both systems and selves.
Seems an even more interesting character.
Create a simple workshop and button to instantiate a couple of mentors. I created three:
One to teach about Palantir Pipelines
One to teach about Impro: Improvisation and the Theatre
One to be an exercise coach.
I think I need to modify the image generation to use nanobanana-pro, but it will work as a placeholder for now.

I want to refresh the Mentors ‘energy’ through a pseudo sleep cycle. So let’s create a sleep log object

And then create a sleep cycle AIP function

Create an automation, to run the sleep cycle nightly.

Would like mood to also be tracked, but that will be reliant on interactions with the user. So let’s hold off on that one for now.
Probably the central node of the entire experiment really revolves around ‘don’t break the chain’ philosophy of Jerry Seinfield . Or duolingo’s don’t break the streak. Or James Clear and Atomic Habits https://jamesclear.com/plan-failure
It needs to be visual, and it needs to bug nag? Harass? The user each time they don’t check in. This will be the minimum required, at least a daily check in into the system.
To that end, create a check in object type. I will follow this excellent article by Áron Székely (I wish he would write more!)

And then a registered user object

Have it display the user name formatting, change the rules and parameters to take in the user.

For now, lets just register a user using the Object Explorer

Now I need to establish the relationship between the user and the mentors.
Create an ontology object for the join

Enable edits on the object, create an action to create the link object, set params to the registered user and mentor object types.
Make the link

Great, now I need to capture the ‘check in’ add it to the workshop, simple check in button.

Ok, let’s wire up an automation to see if I have checked in by 8 AM. If I haven’t checked in, my linked mentor should reach out to me.
Create a send notification action on the registered user (choose to add the parameter after, and then limit it to a user for input)
Ok, this ends up being a bit of a chaining exercise.
Take in a registered users object as an input

Use an LLM to get the most recent check in timestamp for this user and compare it to current date (i.e. see if a check in has occurred today)

I created a check in object to test the True path.
If it goes down the False path, I want it to follow the link to the mentor

And then call that notification passing it the mentor and the user

If we delete the check in object, we can run the preview

Finally we go to automate, we want to pass in a set of Active registered users, and then for each one run the Check for Check In AIP logic, which if it finds you haven’t checked in will send out the notification.


Then in Automate we can manually execute it and watch as it sends the notification.

There’s a lot of places I think I can take this, but its shaping into an interesting experiment.