<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rohit Durbha</title>
    <description>The latest articles on DEV Community by Rohit Durbha (@rohitsagar).</description>
    <link>https://dev.to/rohitsagar</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4192506%2F0977e347-3079-4d60-a718-fa40d5c50d5d.png</url>
      <title>DEV Community: Rohit Durbha</title>
      <link>https://dev.to/rohitsagar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rohitsagar"/>
    <language>en</language>
    <item>
      <title>No path, no recommendation: an AI agent with graph memory on FalkorDB</title>
      <dc:creator>Rohit Durbha</dc:creator>
      <pubDate>Sun, 18 Oct 2026 18:21:52 +0000</pubDate>
      <link>https://dev.to/rohitsagar/no-path-no-recommendation-an-ai-agent-with-graph-memory-on-falkordb-37bd</link>
      <guid>https://dev.to/rohitsagar/no-path-no-recommendation-an-ai-agent-with-graph-memory-on-falkordb-37bd</guid>
      <description>&lt;p&gt;&lt;em&gt;Built for the WeMakeDevs × FalkorDB hackathon. Primary track: Agent Memory and Coordination. Secondary fit: Agents That Act on Connected Data.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Most tools that read the internet for you end the same way: a feed of links, each with a confident sentence explaining why it matters to you. That sentence is written after the fact, by a model, and nobody can check it.&lt;/p&gt;

&lt;p&gt;NightShift does the opposite. &lt;strong&gt;A recommendation cannot exist unless FalkorDB returns a path from your project to the signal, and that path is the explanation.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The short version:&lt;/strong&gt; NightShift is an always-on developer intern. It connects public technical signals to the project you are actually working on, remembers decisions across sessions, hands work between bounded agents, and explains every recommendation with the graph evidence that produced it. Nothing with a side effect runs without explicit approval.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Repo:&lt;/strong&gt; &lt;a href="https://github.com/pranavkhaspa/knightly" rel="noopener noreferrer"&gt;https://github.com/pranavkhaspa/knightly&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The problem: relevant to whom?
&lt;/h2&gt;

&lt;p&gt;Keyword matching can tell you an article mentions Redis. It cannot tell you whether &lt;em&gt;your project&lt;/em&gt; needs Redis, or why.&lt;/p&gt;

&lt;p&gt;What is missing is relationships. This project has this requirement. That requirement needs this technology. This item mentions that technology. This source published the item. Those are four hops, and a relational table with a keyword column flattens every one of them.&lt;/p&gt;

&lt;p&gt;That is why the store had to be a graph, and why FalkorDB is the product store here, not a visualization layer bolted on at the end.&lt;/p&gt;




&lt;h2&gt;
  
  
  The one rule: no path, no recommendation
&lt;/h2&gt;

&lt;p&gt;Every recommendation has to survive this query. It lives in the graph repository, not in an HTTP handler or an agent prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="k"&gt;MATCH&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;p:&lt;/span&gt;&lt;span class="n"&gt;Project&lt;/span&gt; &lt;span class="ss"&gt;{&lt;/span&gt;&lt;span class="py"&gt;id:&lt;/span&gt; &lt;span class="n"&gt;$project_id&lt;/span&gt;&lt;span class="ss"&gt;})&lt;/span&gt;
  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:HAS_REQUIREMENT&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;r:&lt;/span&gt;&lt;span class="n"&gt;Requirement&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:NEEDS&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;tech:&lt;/span&gt;&lt;span class="n"&gt;Technology&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:MENTIONS&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;item:&lt;/span&gt;&lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:FROM&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;source:&lt;/span&gt;&lt;span class="n"&gt;Source&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;item.id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;$item_id&lt;/span&gt;
&lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="n"&gt;p.id&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;project_id&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;r.id&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;requirement_id&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;tech.id&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;technology_id&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;item.id&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;item_id&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;source.id&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;source_id&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt;
       &lt;span class="nf"&gt;nodes&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;path_nodes&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In one line: &lt;code&gt;User → Project → Requirement → Technology ← Item → Source&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If the query returns nothing, the item is not a recommendation. It can still be shown as unconnected ingestion data, but it never gets a graph-backed score. When it does return a path, the recommendation stores the query name, ranking version, matched IDs, source, evidence and a readable path. The UI renders the path the graph returned. It does not ask a model to invent an explanation afterwards.&lt;/p&gt;

&lt;p&gt;Pull FalkorDB out and you do not lose a chart. You lose the relationships that make the product work.&lt;/p&gt;




&lt;h2&gt;
  
  
  One store, no shadow database
&lt;/h2&gt;

&lt;p&gt;The first draft of our spec had SQLite as an operational store. We dropped it. &lt;strong&gt;FalkorDB is the only durable application state store&lt;/strong&gt;: projects, graph paths, tasks, leases, idempotency records, memories, decisions, tool calls and approved actions.&lt;/p&gt;

&lt;p&gt;Two stores means a question about "what did the user decide?" can be answered from the wrong one. So the rule is strict. If a crash-replay spool is ever needed, it can only be an at-least-once transport buffer, deleted after the graph acknowledges the write, and it can never answer a product query.&lt;/p&gt;

&lt;p&gt;The practical payoff is simple: restart the daemon and the dashboard is rebuilt from FalkorDB, including the active project path and persisted tasks.&lt;/p&gt;

&lt;p&gt;The graph layout:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Graph&lt;/th&gt;
&lt;th&gt;What it holds&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nightshift_control&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;user-to-graph mapping, schema version, deployment metadata, leases and idempotency records&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nightshift_u_&amp;lt;stable-id&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;profile and project context, sources and items, recommendations and evidence, sessions, memories, decisions, agents, tasks, tool calls, action proposals and approvals&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;User graph names come from a stable hashed identifier. A raw email, display name or token never appears in a graph name, and every user-owned node also carries &lt;code&gt;tenant_id&lt;/code&gt; and &lt;code&gt;user_id&lt;/code&gt; for defense-in-depth filtering.&lt;/p&gt;




&lt;h2&gt;
  
  
  Memory that supersedes instead of overwriting
&lt;/h2&gt;

&lt;p&gt;Memory is append-oriented and typed: &lt;code&gt;episodic&lt;/code&gt;, &lt;code&gt;semantic&lt;/code&gt;, &lt;code&gt;procedural&lt;/code&gt; or &lt;code&gt;operational&lt;/code&gt;. When something changes, the new memory points at the old one with a &lt;code&gt;SUPERSEDES&lt;/code&gt; relationship. History stays queryable. Every memory that influences a recommendation keeps its &lt;code&gt;DERIVED_FROM&lt;/code&gt; link back to evidence.&lt;/p&gt;

&lt;p&gt;Retrieval has a fixed order: current task and session, active project, recent decisions and feedback, stable preferences, then older graph-connected memories. Each retrieval is bounded by rows and bytes, so memory can't quietly grow into a context dump.&lt;/p&gt;




&lt;h2&gt;
  
  
  Agents get five tools, not a database
&lt;/h2&gt;

&lt;p&gt;The agent surface is MCP, but narrow and typed. It is not an arbitrary Cypher endpoint:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;context.search_relevant_items&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;context.explain_recommendation&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;memory.retrieve&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;planner.propose_plan&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;feedback.record&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every invocation becomes a &lt;code&gt;ToolCall&lt;/code&gt; node linked to a task and a session. The model cannot choose a graph name, run arbitrary Cypher, run shell commands, fetch arbitrary URLs, read credentials or perform a direct external write. Scope comes from the installation, never from tool input.&lt;/p&gt;




&lt;h2&gt;
  
  
  Coordination without a second system
&lt;/h2&gt;

&lt;p&gt;Multiple daemons can share a user graph, so scheduler and task leases live in the graph too. A lease is keyed by source or task ID, with an instance heartbeat and a lease token. A worker stores its result only while its token is valid, so a stale worker cannot publish after another one recovers the lease. Abandoned work is converted to an explicit failed state by recovery routines rather than silently continuing.&lt;/p&gt;

&lt;p&gt;Work moves between agents as &lt;code&gt;Task&lt;/code&gt; nodes: &lt;code&gt;Task -[:HANDED_OFF_TO]-&amp;gt; Task&lt;/code&gt;, &lt;code&gt;Task -[:ASSIGNED_TO]-&amp;gt; Agent&lt;/code&gt;. The Relevance-to-Planner handoff is a graph relationship you can query, not a message that disappeared into a queue.&lt;/p&gt;

&lt;p&gt;How we check it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;make concurrency-evidence&lt;/code&gt; runs a 32-caller in-memory coordination harness 100 times under the Go race detector.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;FALKORDB_INTEGRATION=1 make integration-test&lt;/code&gt; runs against a live FalkorDB using unique temporary graphs, verifies graph-backed ingestion and evidence, action idempotency and concurrent lease completion, then deletes those graphs.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Approval is a property of the system, not of the prompt
&lt;/h2&gt;

&lt;p&gt;"Please ask before doing anything destructive" is a wish. We wanted it to be a property of the runtime.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;External actions are &lt;strong&gt;disabled by default&lt;/strong&gt; (&lt;code&gt;NIGHTSHIFT_ACTIONS_ENABLED=false&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;A plan stays &lt;code&gt;proposed&lt;/code&gt; until the user explicitly approves it. Its state and idempotency record live in FalkorDB.&lt;/li&gt;
&lt;li&gt;Tenant, user and approver come from trusted deployment config, a verified OIDC token, or a signature-verified proxy. HTTP clients cannot choose them, and a client-supplied &lt;code&gt;approved_by&lt;/code&gt; is ignored.&lt;/li&gt;
&lt;li&gt;Gmail and Calendar use read-only OAuth scopes and the adapters only issue &lt;code&gt;GET&lt;/code&gt; requests. GitHub access is behind a repository allowlist, and force-push and auto-merge are always refused.&lt;/li&gt;
&lt;li&gt;Anything NightShift reads from outside is treated as hostile. Stored excerpts are bounded and tagged with &lt;code&gt;untrusted_origin&lt;/code&gt; (&lt;code&gt;web&lt;/code&gt;, &lt;code&gt;mail&lt;/code&gt;, &lt;code&gt;calendar&lt;/code&gt;, &lt;code&gt;github&lt;/code&gt;). Message bodies and raw pages are never persisted.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Letting an agent write code, carefully
&lt;/h2&gt;

&lt;p&gt;NightShift can optionally hand a scoped coding task to OpenCode. You type something like &lt;code&gt;Fix the authentication bug&lt;/code&gt; in a conversation, and then:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;NightShift stores the request and bounded project context as a durable task in FalkorDB.&lt;/li&gt;
&lt;li&gt;A serial queue worker claims it and creates an isolated Git worktree.&lt;/li&gt;
&lt;li&gt;OpenCode edits that worktree. NightShift collects the event stream and the diff.&lt;/li&gt;
&lt;li&gt;The configured tests run, and the outcome is posted back to the conversation.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The guardrails matter more than the flow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Git worktree separates edits from your checkout, but &lt;strong&gt;it is not a sandbox&lt;/strong&gt;, and the docs say so plainly.&lt;/li&gt;
&lt;li&gt;OpenCode's shell and external-directory tools are hard-denied by a server policy that is supplied outside the project code, because a task can edit files in its own worktree.&lt;/li&gt;
&lt;li&gt;Tests run from a trusted argument vector such as &lt;code&gt;["go","test","./..."]&lt;/code&gt;. A model-generated command is never executed.&lt;/li&gt;
&lt;li&gt;Failed tests leave the task blocked for review. NightShift never commits, pushes, opens a pull request or deploys.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  It runs on a small box
&lt;/h2&gt;

&lt;p&gt;NightShift is one native Go daemon. It needs no Node.js, Python, Docker or SQLite at runtime. Static binaries build for old x86 PCs and ARM64 boards:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;GOOS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;linux &lt;span class="nv"&gt;GOARCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;arm64 &lt;span class="nv"&gt;CGO_ENABLED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0 go build &lt;span class="nt"&gt;-trimpath&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; dist/nightshift-linux-arm64 ./cmd/nightshift
&lt;span class="nv"&gt;GOOS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;linux &lt;span class="nv"&gt;GOARCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;amd64 &lt;span class="nv"&gt;CGO_ENABLED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0 go build &lt;span class="nt"&gt;-trimpath&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; dist/nightshift-linux-amd64 ./cmd/nightshift
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a device lacks the memory for FalkorDB, the graph can stay remote. The same binary also runs under systemd on a VPS, or as a stateless service on Render, as long as every instance shares one FalkorDB endpoint.&lt;/p&gt;

&lt;p&gt;One detail we like: &lt;code&gt;/health/live&lt;/code&gt; never touches the graph, while &lt;code&gt;/health/ready&lt;/code&gt; probes it and returns &lt;code&gt;503&lt;/code&gt; when it is unreachable. A graph outage therefore stops traffic without sending a healthy process into a restart loop.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;source&lt;/span&gt; .env&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; +a
docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; deploy/docker/compose.yaml up &lt;span class="nt"&gt;-d&lt;/span&gt; falkordb
go mod download
go run ./cmd/nightshift
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then trigger the deterministic public-fixture flow and inspect the evidence:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsS&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:8080/api/v1/runs
curl &lt;span class="nt"&gt;-fsS&lt;/span&gt; http://127.0.0.1:8080/api/v1/recommendations
curl &lt;span class="nt"&gt;-fsS&lt;/span&gt; http://127.0.0.1:8080/api/v1/graph/path/&amp;lt;recommendation-id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Record feedback and turn the recommendation into a proposed plan:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsS&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:8080/api/v1/recommendations/&amp;lt;recommendation-id&amp;gt;/feedback &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"kind":"useful","note":"Connected to the active project."}'&lt;/span&gt;

curl &lt;span class="nt"&gt;-fsS&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:8080/api/v1/recommendations/&amp;lt;recommendation-id&amp;gt;/plan &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"goal":"Prepare the smallest implementation task."}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The plan stays &lt;code&gt;proposed&lt;/code&gt; until a human approves it. Open &lt;a href="http://127.0.0.1:8080/" rel="noopener noreferrer"&gt;http://127.0.0.1:8080/&lt;/a&gt; for the embedded status page, which shows the active graph path.&lt;/p&gt;




&lt;h2&gt;
  
  
  What we measured, and what we didn't
&lt;/h2&gt;

&lt;p&gt;Covered by automated checks: bounded source failures and recovery, approval-gated action retries, graph evidence persistence, exactly-once lease behaviour, and the auth and configuration boundaries.&lt;/p&gt;

&lt;p&gt;We are &lt;strong&gt;not&lt;/strong&gt; claiming numbers for memory, CPU, startup time or dashboard latency, and not for any particular ARM board. Those targets stay unmeasured until the workload is run on the target hardware and the output is recorded. Deterministic mode is the baseline. Live Gmail, Calendar and search provider credentials are deployment-specific.&lt;/p&gt;




&lt;h2&gt;
  
  
  What we would tell someone starting a graph-backed agent
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Make the invariant a query, not a prompt.&lt;/strong&gt; "Only recommend what's relevant" is an instruction. "No path, no recommendation" is a &lt;code&gt;MATCH&lt;/code&gt; that returns rows or doesn't.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One durable store removes a whole class of bugs.&lt;/strong&gt; Leases, memory, decisions and tasks in the same graph means there is no second place for the truth to drift.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Narrow, typed tools beat clever prompts.&lt;/strong&gt; Five fixed tools with scope taken from the installation are easier to reason about, and to audit, than one flexible one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;State what you haven't measured.&lt;/strong&gt; A hackathon project that says "this number is unmeasured" is more believable than one that guesses.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>go</category>
      <category>database</category>
      <category>hackathon</category>
    </item>
  </channel>
</rss>
