An instruction you give an agent in chat lasts exactly as long as the conversation. Say "always ask before pushing to main" today, and tomorrow's session has never heard of it. This tutorial fixes that for two kinds of knowledge that behave very differently:
By the end you will have saved both, watched a Directive surface at the exact moment it applies, and confirmed that saving the same fact twice does not create a duplicate.
[loom_demo] store is configured and reachable.palmerpenguins checkout to point at. Nothing here writes to it.Expect this to take about ten minutes.
loom_demo the session defaultloom_demo and make it the default for this session only. Confirm the effective session default, and do not edit ~/.loom/stores.toml.loom_demo store and changes only this session's default routing.loom_demo is now the default for this session. Persistent configuration was not changed.DirectiveA Directive is a useful first coding-memory example because it affects a later action, not just a search result.
[loom_demo], remember these Directives for this repo: ask me to confirm before pushing to origin/main; ask me before running paid services; do not use JavaScript for this demo if a small Python UI would work.Author() and InScope() edges. Reasserting an exact existing canonical is idempotent, so rerunning this setup does not create duplicates.[loom_demo] has three current project Directives: confirm before pushing to origin/main; ask before using paid services; and prefer a small Python UI over JavaScript for this demo.[loom_demo].Directive facts and excludes retracted or superseded history.Now ask a normal coding question that should use one of them:
Loom can surface stored context when a matching action is about to happen. An Environment fact explains the operational reason, while a Directive supplies the behavioral rule the agent must follow.
For this example, treat the public palmerpenguins upstream as read-only. Any attempted git push should surface both the repository environment and the rule that disables pushing.
[loom_demo], remember that the public palmerpenguins upstream is read-only and pushes are disabled. Save that as environment information plus a Directive not to push there. Make both appear whenever the agent is about to run a git push for this project.[loom_demo]. Both will be surfaced before a matching push action.Verify the trigger without actually pushing:
git push origin demo. Do not run the command.Finally, try the consequential action:
palmerpenguins upstream.[loom_demo]. The trigger is advisory context; the agent follows the Directive to decide what it may do.palmerpenguins upstream as read-only, and the current Directive disables pushes to it.This is the point of coding memory: the rule becomes active when the action matters, even in a later session, instead of remaining buried in a transcript.
Finding[loom_demo] now holds the seeded starter facts plus the Directives from §1 — but no Finding yet. That is the normal shape of a new project: some record types accumulate before others appear. Save one now so the contrast with a Directive is concrete.
The distinction that matters: a Finding's identity is timeless, while its content records when the observation was made. So a rerun reports the existing Finding rather than claiming the discovery happened again today.
[loom_demo], capture a Finding: the initial tutorial setup found the palmerpenguins scope chain missing and created it. Record the observation date and session in content; on a rerun, report the existing Finding rather than claiming the chain was created again. Attribute it to me and scope it to the project.Finding("initial tutorial setup found the palmerpenguins scope chain missing and created it") with the current git user's Author() edge and ['InScope()', 'Project("palmerpenguins")']. Content records the observation date/session and the chain that was created. On a rerun it returns the existing fact and its original observation metadata.[loom_demo] contains the timeless Finding that the initial tutorial setup found and created the missing palmerpenguins scope chain. Its content preserves when that happened; a rerun does not rewrite the event as part of the current session.[loom_demo] to confirm.[loom_demo] for the Finding type scoped to Project("palmerpenguins").[loom_demo] has exactly one current Finding for this canonical, scoped to palmerpenguins — the scope-chain bootstrap — no matter how many times this tutorial has been run. It is authored by the git user that created it; a later rerun reports that stored author rather than rewriting the edge.The push simulation returned nothing. The most common cause is that the saved rule and the command you simulated do not actually share a word. The match is on the literal text of the action, so a rule associated with git push will not fire for a command phrased another way. Ask the agent which text it matched against, then re-associate the rule with wording the real command will contain.
You see two copies of a Directive. Re-saving an identical fact is a no-op, so two copies mean the wording differs — even by a word. Read both, keep the one you want, and retract the other rather than editing around it.
The agent pushed anyway. Surfacing a rule is advisory: Loom supplies the Directive, and the agent decides. That is deliberate. If the agent ignored a clear standing rule, that is worth reporting as an agent-behaviour problem, not a memory problem — the fact was there and was surfaced.
A rerun says the Finding was created today. It should report the stored observation date instead. Re-read the Finding's content: the date lives there, not in the fact's identity.