Skip to content

Personal Project — Agentic GW2 Companion (Planning & Optimization) ​

Working language for this project: English. This document is the single source of truth. We deep-dive section by section and keep it updated with decisions and open questions.

Context ​

I'm a lead frontend (React) engineer. I want a personal project to:

  • Priority #1 — master an AI-assisted, spec-driven development workflow (the "agentic mindset"). Not to become an AI specialist, but to build much faster by orchestrating AI agents (Claude Code) through a disciplined workflow (Spec-Driven Development): specs as source of truth, plan-before-code, review instead of type, guardrails (tests/types) that let me trust the agent. See Working method below.
  • Practice a modern full-stack: React (frontend) + NestJS (backend).
  • Explore backend performance (concurrency, real-time, throughput, data pipelines).
  • Stand up a real DevOps pipeline (CI/CD, observability, scalability).
  • On a theme that motivates me: Guild Wars 2.

Note: "agentic" here means how I build (AI-orchestrated, spec-driven), not stuffing LLM agents into the product. The GW2 tool is the vehicle for practising the workflow. Any LLM feature in the product itself is a secondary nice-to-have, not the core.

Hard requirement learned the hard way: it must be a project I actually use and won't abandon. That means a real tool that helps me play, not an abstract tech demo.

The idea (crystallized) ​

Build an agentic companion service (FE + BE) that helps me play Guild Wars 2 better, focused on planning & optimization. I connect my account (GW2 API key), give it a goal, and a team of agents turns it into an optimized, personalized, tracked plan — using my real account state, the GW2 API, Trading Post prices, and the GW2 Wiki.

Why this fits the goals ​

  • Agentic-first by nature: helping-with-a-game is intrinsically tool-use + orchestration + memory heavy.
    • Tool use: GW2 API (account, materials, wallet, unlocks, crafting levels, TP prices), GW2 Wiki API (knowledge/RAG), recipe/ingredient graph.
    • Planning as the core mechanic: goals (a legendary, a collection) are dependency trees → decompose → resolve prerequisites → optimize acquisition (buy vs craft vs farm) → sequence into steps.
    • Heuristic vs LLM with a real payoff: graph/cost optimization = pure computation (cheap, exact); understanding fuzzy goals and reasoning over wiki knowledge = LLM. The comparison is built in.
    • Persistent memory: the tool knows my account and progress, and re-plans as I advance or as prices move.
  • Sticky: I'll use it every session because it solves my own problem.

Flagship MVP — Legendary crafting planner ​

First vertical (deliberately just one — it's already large and complex):

I name a legendary (e.g. The Bifrost). The agent reads my account, expands the full crafting dependency tree, checks what I already own, computes the cheapest buy-vs-craft path against live TP prices, estimates gold + time, produces a step-by-step plan, and tracks me toward it across sessions.

Two personas (both matter; the second is mine) ​

  1. Craft-for-self: "I want The Bifrost for myself" → cheapest acquisition path, actionable plan, progress tracking.
  2. Craft-for-profit (my actual use case): "Which legendaries are the most profitable to craft and sell right now?" → rank sellable legendaries by margin, show the optimal production path, factor in the time-gated inputs I can supply, tell me what's worth crafting.

Differentiator ​

Static calculators exist (e.g. gw2efficiency). Our edge is the agentic, conversational, goal-driven, self-updating layer on top: understand a fuzzy goal, reason over account + wiki + prices, produce and maintain a living plan.

Domain & data model (verified against the official GW2 API wiki) ​

GW2 API v2 surface (endpoints we'll use) ​

  • Account state (needs API key): /v2/account/materials (material storage), /v2/account/wallet (currencies), /v2/account/bank, /v2/account/inventory, /v2/characters/:id/inventory, /v2/characters/:id/crafting (disciplines + level/rating, max 500), /v2/account/recipes (unlocked recipes).
  • Item/recipe data (no auth): /v2/items (fields incl. flags[] for binding — AccountBound, SoulbindOnAcquire…), /v2/recipes + /v2/recipes/search?input=|output= (station recipes only).
  • Trading Post (no auth): /v2/commerce/prices (best buys.unit_price / sells.unit_price), /v2/commerce/listings (full order-book depth — use when buying/selling large quantities across price levels).
  • Auth & scopes: Authorization: Bearer <key>; scopes needed = account, inventories, wallet, characters, unlocks (+tradingpost only for the player's own orders/history).
  • Rate limit: per-IP token bucket — 300 burst, refill 5/sec (300/min), 429 on overflow. Batch up to 200 ids per ?ids= call.

The critical data-sourcing fact ​

Mystic Forge recipes are NOT in the API. /v2/recipes only covers the 9 crafting disciplines/stations; the Mystic Forge is not a discipline. So every legendary combine step — precursor forging, Gift of Fortune / Mastery / Magic / Might, Mystic Clovers, the weapon-specific gift, and the final 4-item assembly — is absent from the API. Every existing tool supplies these from the wiki / a curated dataset.

→ Data source = hybrid (decision):

  • Official API for station-crafted leaves + live prices + account state.
  • A curated Mystic Forge recipe table (from the GW2 Wiki) for the Forge nodes. This curated table is the project's key maintenance point (game patches drift the numbers).
  • Resolve every leaf item id → price via /v2/commerce/prices.

Legendary structure (Gen 1, example: The Bifrost) ​

Built in the Mystic Forge from 4 items: Precursor (The Legend) + Gift of Fortune + Gift of Mastery + Gift of The Bifrost.

  • Gift of Fortune = Gift of Magic + Gift of Might + 77 Mystic Clovers + 250 Globs of Ectoplasm.
  • Gift of Mastery = Bloodstone Shard + 250 Obsidian Shards + Gift of Exploration + Gift of Battle.
  • Gift of <weapon> = weapon-specific (runestones, gold, discipline-crafted gift…).

Buyable vs account-bound (drives the profit model) ​

  • Buyable on TP: precursors, Globs of Ectoplasm, Mystic Coins, T6 fine mats, Icy Runestones, and station-crafted ingredients.
  • Account-bound / earned (NOT on TP): Gift of Exploration (100% world completion), Gift of Battle (WvW reward track), Bloodstone Shard (spirit shards), Obsidian Shards (karma), Mystic Clovers (RNG forge). These are a time cost, not a gold cost.
  • Classify each leaf programmatically via item flags[].

Profit model (confirmed) ​

profit = net_sell_price(legendary) − Σ cost(buyable leaf mats), where:

  • net_sell_price = TP price of the finished Gen 1 legendary minus the fixed 15% TP tax (5% listing + 10% exchange — hardcode it, not an API field).
  • account-bound/time-gated inputs are treated as player-supplied (cost 0, or an assigned opportunity cost).
  • optionally subtract already-owned mats (from account endpoints) to get my personal cost.
  • Optimization question: given the gated inputs (Gifts of Exploration/Battle, Clovers) I can produce, which Gen 1 legendaries maximize total profit / profit-per-gated-input?
  • Prices are volatile → recompute against live TP data and re-check over time.

Verticals backlog (after the flagship) ​

  • Weekly time optimizer: "given my goals + playtime, what should I do this session/week" (dailies, weeklies, resets).
  • Achievement / goal roadmap: turn any long-term goal (mount, title, mastery) into a tracked step-by-step roadmap.
  • Gearing & builds: optimize stat combos, ascended/legendary gear, build templates for a role/mode.

Working method — Spec-Driven Development (the core skill to master) ​

The spec is the durable source of truth; code is cheap to (re)generate. Invest in specs and review; the agent does the typing. Per-feature loop:

  1. Spec — short markdown in the repo (specs/<feature>.md): problem, user story, in/out of scope, acceptance criteria, constraints.
  2. Plan — feed the spec to Claude Code, use plan mode, review/refine the implementation plan before any code.
  3. Tasks — break the plan into small, independently verifiable steps.
  4. Implement — agent writes each task; I review the diff, not author it.
  5. Verify — tests + types + running the app are the guardrails that make agent output trustworthy; derive acceptance tests from the spec's criteria.
  6. Capture — record conventions/decisions in CLAUDE.md (the project's constitution); turn repeatable steps into slash commands / subagents.

Mindset: I'm the architect + reviewer, not the typist. Small increments + strong guardrails = trust + speed. Reference: GitHub Spec Kit formalises this spec→plan→tasks→implement loop; Claude Code plan mode, CLAUDE.md, and subagents are the built-in primitives.

Why GW2 suits this: clean verifiable slices (the profit calc has a right answer; the recipe graph is well-defined; the API is documented) → strong guardrails → ideal conditions to practise trusting + reviewing an agent.

Architecture (to affine section by section) ​

Planning engine (mostly deterministic; LLM optional) ​

  • Core is a deterministic engine, not a swarm of agents: recipe-graph resolver → buy-vs-craft/profit optimizer → account-state diff → live price fetch. This has right answers → easy to test → great SDD guardrails.
  • Optional thin LLM layer only where judgment helps: parsing a fuzzy goal ("something profitable under ~500g upfront") into structured constraints, and light wiki reasoning. Deferred; not required for the MVP.
  • If/when an LLM tool-use loop is added, build it on the official @anthropic-ai/sdk (Tool Runner) — but it's a secondary feature, not the point of the project.

Backend (NestJS) — DECIDED: lean MVP, Postgres + in-memory cache ​

Module structure:

  • Gw2ApiModule — typed GW2 API client; owns auth (user API key), rate-limit budgeting (300/min per-IP token bucket), 200-id batching.
  • StaticDataModule — items + station recipes (immutable) synced once & cached hard; holds the curated Mystic Forge table (wiki-sourced; the API can't provide it).
  • RecipeGraphModule — merges API recipes + curated Forge table → full dependency graph; memoized tree expansion.
  • PricingModule — live TP prices, short-TTL in-memory cache; buy-vs-craft cost resolution.
  • PlanningModule — the optimizer: expand tree → classify leaves buyable/account-bound via flags[] → profit = net_sell − Σ buyable_cost → rank Gen 1 legendaries.
  • AccountModule — reads user materials/wallet/crafting to personalise (subtract owned mats).
  • Auth/UserModule — accounts + encrypted GW2 API-key storage.

The optimizer is a clean recursive computation (cost = min(buy_price, Σ children craft cost)) with right answers → ideal for unit tests = the SDD guardrail.

Perf posture (decided: "just enough"): honest framing — this is I/O-bound API orchestration, not a concurrency/throughput system. Perf = sensible caching + batching + rate-limit budgeting (good hygiene), not an elaborate pipeline. backend performance is downgraded from a headline goal to good practice here.

Infra (decided): Postgres (users, cached static data, curated Forge table) + in-memory cache for the MVP. Redis is a later add if/when the caching story is worth showcasing.

Real-time: deferred. Recompute margins on demand / on refresh for the MVP; WebSocket live-updating rankings is a stretch goal, not MVP.

Frontend (React) — DECIDED ​

  • MVP centerpiece (decided): plan / tree view for ONE legendary — pick a legendary → full dependency tree + step plan + own-vs-need + buy-vs-craft per node. This is the thinnest end-to-end slice; the profit ranking view is the immediate next layer (same engine run across all Gen 1 legendaries, sorted).
  • Tree visualization (decided): nested collapsible list — indented expandable rows with cost roll-ups and gated-input flags. Simplest MVP baseline; can upgrade to React Flow / d3 later for visual polish.
  • Surfaces beyond MVP: profit ranking (persona money-shot), account dashboard, (stretch) fuzzy goal input.
  • Honest note on FE perf: the original "render huge real-time datasets (virtualization/Web Workers)" challenge isn't naturally present (tree ≈ few hundred nodes, ranking ≈ 19 items). The FE strength here is dataviz quality + clean UX, not rendering-perf. Don't bend the product to manufacture a virtualization flex.

DevOps — DECIDED: right-sized, workflow-first ​

  • CI/CD (GitHub Actions): lint + typecheck + test + build on PR, deploy on merge. Pairs with SDD — acceptance tests become the guardrail CI enforces ("trust the agent" → "CI proves it"). Do it early.
  • Containerization: Dockerfile for the NestJS API + Docker Compose for local (API + Postgres).
  • Deployment (decided): managed PaaS — Fly.io / Railway. Push-to-deploy, managed Postgres, free tiers. Fast to a live public URL; fits "workflow not infra" focus.
  • Observability (decided: lean): structured logs (pino) + Sentry (error tracking) + health checks & a few request metrics.
  • Dropped from the original scope (were tied to the abandoned swarm): ❌ Kubernetes, ❌ chaos engineering, ❌ heavy load testing (k6/Locust), ❌ agent/LLM cost tracing. Keeps the MVP lean.
  • Honest framing: a complete, right-sized DevOps story (CI/CD + containers + real deploy + error tracking), not a "scale to millions" story — the correct call given priority = workflow, not infra.

Deep-dive plan (order of sections) ​

  1. Concept & MVP scope — lock flagship, define the thinnest end-to-end slice. (mostly done)
  2. Domain & data modeling — GW2 API surface, recipe/dependency graph, wiki RAG, account state, caching, the profit model. (done — verified)
  3. Working method (SDD) setup — repo skeleton, CLAUDE.md constitution, specs/ layout, first feature spec + acceptance criteria, plan-mode workflow. (the priority-#1 skill)
  4. Planning engine — deterministic recipe-graph + buy-vs-craft/profit optimizer; test strategy (the guardrails).
  5. Backend (NestJS) — services, engine wiring, API sync/caching, real-time, perf.
  6. Frontend (React) — plan viz, goal input, dashboard.
  7. DevOps & observability — CI/CD, deploy, metrics/tracing.
  8. Portfolio framing — tell the story (the SDD workflow itself is part of the story).

Open questions / decisions to make ​

Resolved:

  • Recipe-graph data source → hybrid (API + curated Mystic Forge table).
  • Infra/perf → lean; Postgres + in-memory cache; I/O-bound, no heavy pipeline.
  • Deploy/observability → managed PaaS (Fly/Railway) + logs/Sentry/health.
  • Orchestration / LLM-in-product → deterministic engine core; LLM optional & deferred.
  • API sync/cache → static data cached hard (immutable), prices short-TTL, respect 300/min + 200-id batching.

Still open (implementation-time):

  • How to build & maintain the curated Mystic Forge dataset (scrape wiki once vs hand-curate; keeping it patch-current).
  • How to price/value account-bound gated inputs (cost 0 vs opportunity cost vs "profit per gift of exploration").
  • Exact test strategy for the optimizer (fixtures, golden values) — the SDD guardrail.
  • LLM provider/model + cost control — only if/when the optional fuzzy-goal feature is built (default to latest Claude via @anthropic-ai/sdk).

Final goal ​

A rich portfolio project that demonstrates:

  • Mastery of an AI-assisted, spec-driven development workflow — shipping fast by orchestrating agents, with specs as source of truth and guardrails I trust (the priority-#1 skill).
  • Strong full-stack React/NestJS with real backend performance work.
  • A complete, professional DevOps chain.
  • And — most importantly — a tool I actually use to plan and profit from legendary crafting in GW2.