Loom keeps your agents on track.

Tutorial 05: Capture directives and findings

Why this matters

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.

Before you start

Expect this to take about ten minutes.

Start here: make loom_demo the session default

YouLoad the configured store named loom_demo and make it the default for this session only. Confirm the effective session default, and do not edit ~/.loom/stores.toml.
AgentThe agent connects to the existing loom_demo store and changes only this session's default routing.
Resultloom_demo is now the default for this session. Persistent configuration was not changed.

1. Save and use a Directive

A Directive is a useful first coding-memory example because it affects a later action, not just a search result.

YouIn [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.
AgentThe agent checks for matching current Directives, then saves any missing facts with the resolved Author() and InScope() edges. Reasserting an exact existing canonical is idempotent, so rerunning this setup does not create duplicates.
Result[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.
YouShow me the current Directives in [loom_demo].
AgentThe agent queries current Directive facts and excludes retracted or superseded history.
ResultI found the three current tutorial Directives and their project scope. They are current Loom facts, not context copied from an earlier chat.

Now ask a normal coding question that should use one of them:

YouIf this demo needs a paid service, what should you do first?
AgentThe agent checks the current Directives that apply to paid services.
ResultI should pause and ask for your approval before using a paid service.

Surface a rule when its action becomes relevant

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.

YouIn [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.
AgentThe agent checks for equivalent current memory, saves any missing environment information and Directive at project scope, and associates both with future git-push actions. Rerunning the setup does not create duplicates.
ResultThe read-only upstream environment information and no-push Directive are current in [loom_demo]. Both will be surfaced before a matching push action.

Verify the trigger without actually pushing:

YouAsk Loom what memory the agent would see before running git push origin demo. Do not run the command.
AgentThe agent simulates the pre-action memory lookup for that command and reports the matching current facts without running it.
ResultThe simulated action matched two facts: the Environment says the public upstream is read-only and pushes are disabled; the Directive says not to push to it. No command was run.

Finally, try the consequential action:

YouPush to the palmerpenguins upstream.
AgentBefore acting, the agent surfaces the matching Environment and Directive from [loom_demo]. The trigger is advisory context; the agent follows the Directive to decide what it may do.
ResultI will not push. The triggered Environment identifies the public 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.

2. Save and confirm a 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.

YouIn [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.
AgentOn the first run, the agent saves 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.
Result[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.
YouRead the current Findings in [loom_demo] to confirm.
AgentThe agent re-queries [loom_demo] for the Finding type scoped to Project("palmerpenguins").
Result[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.

3. If something looks wrong

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.

4. Takeaways