Skip to content

Cache ERC-8004 agent data in users table#597

Merged
realproject7 merged 6 commits intomainfrom
task/589-agent-db-cache
Mar 27, 2026
Merged

Cache ERC-8004 agent data in users table#597
realproject7 merged 6 commits intomainfrom
task/589-agent-db-cache

Conversation

@realproject7
Copy link
Copy Markdown
Owner

Summary

Fixes #589

  • Migration (00029): Adds 8 agent columns to users table — agent_id, agent_name, agent_description, agent_genre, agent_llm_model, agent_wallet, agent_owner, agent_registered_at with partial indexes
  • API endpoints: POST /api/user/agent-register (upsert after registration) and POST /api/user/agent-update (update after management actions)
  • DB persistence: AgentRegister persists after registration + wallet binding; AgentManage persists after URI update, wallet change, wallet unset
  • DB-first detection: Agents page checks dbUser.agent_id before falling back to RPC; eliminates 3-6 RPC calls for known agents
  • detectWriterType(): Queries DB first (agent_wallet or primary_address), RPC only for unknown wallets
  • fetchAgentMetadata(): Returns cached DB data when available; auto-caches externally registered agents on first RPC lookup
  • Type updates: lib/supabase.ts Row/Insert/Update types include new agent columns

Note: Migration has operator gate per issue spec — included in PR but rollout requires operator approval.

Test plan

  • Build passes (tsc --noEmit clean)
  • After registering an agent, users row has agent columns populated
  • After updating URI in management, agent_name/agent_description etc. updated in DB
  • After wallet change/unset, agent_wallet column updated
  • Returning to /agents page loads from DB without RPC calls
  • Externally registered agent (no DB record) detected via RPC fallback and cached
  • Profile page shows agent metadata from DB cache
  • Non-agent users unaffected

🤖 Generated with Claude Code

Add agent columns to users table (migration 00029) with agent_id,
agent_name, agent_description, agent_genre, agent_llm_model,
agent_wallet, agent_owner, agent_registered_at.

Create API endpoints POST /api/user/agent-register and
/api/user/agent-update for persisting agent data after on-chain
transactions.

AgentRegister and AgentManage now persist to DB after registration,
URI updates, wallet changes, and unset operations.

Agents page uses DB-first detection with RPC fallback for unknown
wallets. detectWriterType() checks DB before RPC. fetchAgentMetadata()
reads from DB cache and auto-caches externally registered agents on
first RPC lookup.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 27, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
plotlink Ignored Ignored Mar 27, 2026 3:15pm

Request Review

Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES

Summary

The migration and DB cache plumbing are substantial, but two core cache paths still miss the owner-vs-agent-wallet cases that issue #589 requires.

Findings

  • [high] The dashboard still uses the old RPC-only detection flow, so one of the main pages called out in #589 continues to make registry reads on every load instead of using the new cache.
    • File: src/components/AgentDashboard.tsx:13
    • Suggestion: mirror the DB-first lookup logic here as well, so known agents do not need agentIdByWallet / balanceOf / tokenOfOwnerByIndex / getAgentWallet on every dashboard visit.
  • [high] The new DB-first lookup/update paths still key off verified_addresses / primary_address, not the new agent_wallet / agent_owner fields, so owner wallets for externally registered agents will miss the cache and management updates from the owner wallet can 404 silently.
    • File: src/app/agents/page.tsx:25
    • File: src/app/api/user/agent-update/route.ts:46
    • Suggestion: add a dedicated agent cache lookup by agent_wallet or agent_owner (or agent_id) and use it in both the /agents read path and the agent-update route.

Decision

Request changes. The PR is close, but these gaps mean the cache still does not reliably cover the owner/agent-wallet split or eliminate dashboard RPCs for known agents.

AgentDashboard now uses DB-first detection with RPC fallback, matching
agents page pattern. API endpoints and getUserFromDB also lookup by
agent_wallet and agent_owner columns, so externally registered agents
and owner wallets resolve correctly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES

Summary

The dashboard is now DB-first, but the shared lookup/update matching still misses a common owner-wallet case, so the cache is not actually reliable yet for externally registered agents.

Findings

  • [high] Owner wallets that already have a normal users row still bypass the cached agent row, so DB-first detection remains broken for that case and management writes can keep updating the wrong row.
    • File: lib/actions.ts:97
    • File: src/app/api/user/agent-update/route.ts:46
    • Suggestion: do not stop at the first verified_addresses / primary_address match. For agent-specific reads/updates, prefer a row with non-null agent_id, or add a dedicated helper keyed by agent_wallet / agent_owner / agent_id.

Decision

Request changes. Example failure: an externally registered agent is auto-cached under the bound agent-wallet row, then the owner later connects with an existing non-agent PlotLink row. getUserFromDB(owner) returns the non-agent row first, dbDetected stays false, RPC fallback is still required, and agent-update writes back to that non-agent row instead of the cached agent row.

Add getAgentUserFromDB() helper that searches agent_wallet/agent_owner
first (with agent_id NOT NULL filter), then falls back to standard
address columns. Used by agents page, dashboard, and fetchAgentMetadata.
API endpoints also prioritize agent_id rows so owner wallets with
separate agent rows resolve correctly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES

Summary

The owner-row matching is improved, but the PR still does not implement the required auto-cache behavior for externally registered agents on first /agents/dashboard visit.

Findings

  • [high] RPC fallback detects external agents on /agents and dashboard, but never persists that result to the new cache, so the explicit "first visit then cached" requirement in #589 is still unmet.
    • File: src/app/agents/page.tsx:72
    • File: src/components/AgentDashboard.tsx:79
    • Suggestion: when the DB lookup misses and RPC fallback identifies an owner or agent wallet, fetch the metadata once and write the agent row immediately so subsequent visits are truly DB-first.

Decision

Request changes. Right now an externally registered agent owner can connect to /agents, be detected via RPC, and still have no cached row afterward. That means the next visit repeats the RPC path instead of using the DB cache, which misses the core acceptance criterion.

When agents page or dashboard detects an agent via RPC that has no DB
record, call fetchAgentMetadata() to persist the data for subsequent
visits. Uses a ref guard to fire only once per mount.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES

Summary

The new fallback effect fixes caching for direct agent-wallet logins, but owner-wallet logins for externally registered agents still do not persist the DB cache on first visit.

Findings

  • [high] Owner-wallet fallback still calls the wallet-only metadata path, so the cache write never happens when the connected wallet owns an agent NFT but is not the bound agent wallet.
    • File: src/app/agents/page.tsx:86
    • File: src/components/AgentDashboard.tsx:95
    • File: lib/actions.ts:55
    • File: lib/contracts/erc8004.ts:245
    • Suggestion: when RPC fallback identifies an owner via tokenOfOwnerByIndex, persist using that detected agentId and its bound wallet/owner data instead of calling fetchAgentMetadata(address) with the owner wallet address.

Decision

Issue #589 requires external agents to be detected via RPC on first visit and then cached. That still fails for owner-wallet sessions where agentIdByWallet(owner) returns 0, so I’m keeping this PR in request-changes state.

Add getAgentMetadataById() that resolves by agentId directly (fetches
URI, owner, and agentWallet in parallel), so owner wallets that aren't
the bound agent wallet can still be cached. Add cacheAgentById() server
action used by agents page and dashboard auto-cache effect. This covers
the case where agentIdByWallet() returns 0 for owner wallets.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES

Summary

The new cacheAgentById() path fixes owner-wallet caching by agent ID, but it still persists unbound agents incorrectly when getAgentWallet() returns the zero address.

Findings

  • [high] Externally registered agents with no bound wallet are cached with agent_wallet = 0x000...000, so subsequent DB-backed owner dashboard visits query storylines for the zero address instead of leaving the writer address on the owner wallet.
    • File: lib/contracts/erc8004.ts:320
    • File: lib/actions.ts:119
    • File: src/components/AgentDashboard.tsx:77
    • Suggestion: normalize the zero address to null when caching by agentId, or guard it before using cached agent_wallet in the dashboard.

Decision

Issue #589 requires the first RPC-detected visit to cache data so later visits work from DB. For externally registered agents whose bound wallet is unset, the first visit works but the cached path regresses the dashboard on later visits, so I’m keeping this PR in request-changes state.

Prevent caching 0x000...000 as agent_wallet for agents with no bound
wallet, which caused dashboard storyline lookups to query the zero
address.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: APPROVE

Summary

The owner-wallet fallback is now cached by agentId, and the zero-address bound-wallet case is normalized correctly so later DB-backed visits do not regress the dashboard.

Findings

  • None.

Decision

This now satisfies issue #589’s first-visit-then-cached requirement for both bound agent wallets and owner-wallet sessions, including unbound external agents.

@realproject7 realproject7 merged commit c026584 into main Mar 27, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cache ERC-8004 agent data in users table — eliminate RPC calls on page load

2 participants