8.0 KiB
OSRS Codex — Entry Schema (v1)
The codex is a client-agnostic knowledge base. Every bot-able OSRS activity is described here once, in a strict YAML structure. AI agents do not read the game — they read a codex entry and translate its abstract actions into whatever client API they target (DreamBot, Microbot, OSBot, RuneLite plugins, custom, ...).
Two invariants make translation reliable:
- One entry = one bot-able activity, described end-to-end.
- Every action references the universal vocabulary (
docs/action-grammar.md). No client-specific calls ever appear in an entry.
File layout
osrs-codex/
docs/
schema.md <- this file
action-grammar.md <- universal action vocabulary
data-sources.md <- where facts come from + verification rules
codex/
economy/ <- money-making: flips, alching, drops, selling
training/ <- level training per skill (per band)
combat/ <- bossing, skilling-in-combat
combat-slayers/ <- slayer-specific
quests/ <- questable XP / requirement unlocks
transport/ <- movement, teleporting, banking logistics
meta/ <- account building, mule/logistics, world setup
schemas/
entry.schema.json <- JSON-Schema for validation
tools/
validate.py <- runs the schema over all codex/**.yaml
INDEX.md <- machine-generated catalog of every entry
An activity that spans domains (e.g. alchemy training and money) lives in
its primary domain; cross-refs go in related.
Entry structure (YAML)
id: alching-nature-runecoins # kebab-case, globally unique
title: Low-Level Alchemy (F2P)
domain: economy # one of the codex/ dirs
tags: [alching, money, f2p, p2p-safe]
status: verified # draft | verified | stale
version: 3
updated: 2026-08-27 # last date facts were re-verified
summary: >
One-sentence description of what the bot does and why it runs.
# ---------------------------------------------------------------- accounts
accounts:
membership: f2p # f2p | members | hybrid (which items)
min_level: 1 # absolute floor to start
requires_quest: [] # quest ids (see codex/quests/)
requires_other: # free-form hard prerequisites
- "A bankable inventory + bank access"
# ---------------------------------------------------------------- setup
best_practice: # REQUIRED — best-in-class execution
equipment:
- item: staff of fire
why: "unlimited fire runes; drops LA rune cost to 1 nature/cast"
source: "OSRS wiki — Staff of Fire; Low Level Alchemy (Cost)"
techniques:
- name: cast on noted (stacked) items
why: "one slot, minimal mouse travel"
source: "OSRS wiki — Low Level Alchemy (Usage)"
# ---------------------------------------------------------------- economy
economy:
cost_per_cycle: 62 # GP consumed per meaningful action
income_per_cycle: 81
net_per_cycle: 19
gp_per_hour_low: 3000
gp_per_hour_high: 6000
xp_per_hour: 14000
supplies: # everything the bot must carry / restock
- item: nature rune
qty_per_cycle: 1
source: ge
ge_limit: 12500 # buy limit / 4h window (verified)
- item: coal
qty_per_cycle: 1
source: ge
ge_limit: 8000
profit_drivers: # what actually makes it profitable
- "Low alch value vs rune+material buy price"
# ---------------------------------------------------------------- state
state_machine:
initial: idle
terminal: [complete, failed]
states:
idle:
goal: reach the banking/crafting location
next: [crafting, bank_supplies]
crafting:
goal: cast Low Level Alchemy on a sellable item
next: [bank_supplies, idle, complete, failed]
bank_supplies:
goal: bank products, withdraw fresh supplies
next: [crafting, idle]
complete:
goal: hit the run's completion condition
failed:
goal: a hard failure — stop, log, alert
transitions:
- from: crafting
when: "runes or materials < buffer"
to: bank_supplies
- from: idle
when: "target level or gp goal reached"
to: complete
# ---------------------------------------------------------------- actions
actions:
- id: a1
step: reach-bank
verb: move_to # <- universal verb (action-grammar.md)
target: bank
params:
location: "Bank of Gielinor"
method: [teleport, walk] # preferred, fallback
on_fail: retry # retry | skip | abort | alert
anti_ban: # OPTIONAL humanisation hints
mouse: "wander 20-80px around target"
delay: [400, 1600]
- id: a2
step: cast-alch
verb: use_item_on
target: "sellable item in inventory"
params:
item: "lowest-alch-value inventory item"
on: "itself"
on_fail: retry
anti_ban:
delay: [900, 2400]
- id: a3
step: bank-loop
verb: bank_inventory
target: bank
params:
deposit: [all products]
withdraw: "supplies up to buffer"
on_fail: alert
# ---------------------------------------------------------------- loop / pacing
run_control:
iteration: "one full craft+bank cycle"
max_iterations: null # null = until complete condition
break: # humanised pause policy
every: [8, 14] # cycles
for: [60, 180] # seconds
stop_conditions:
- "target level reached"
- "gp under floor"
- "hard error 3x"
# ---------------------------------------------------------------- safety
risk:
ban_level: low # low | medium | high
notes:
- "Rune purchase bursts are the main detection vector; pace GE buys."
# ---------------------------------------------------------------- provenance
sources:
- "OSRS Wiki — Low level alchemy (price/limit verified 2026-08-27)"
- "prices.runescape.wiki mapping (item ids + GE limits)"
verified: 2026-08-27
related:
- mule-topup
- f2p-alch-catalog
Every key except actions[].anti_ban, notes, params details is
required (enforced by schemas/entry.schema.json). The validator is
strict — a draft that fails validation blocks the PR.
Best-in-class rule (required)
Every entry MUST declare how a top operator actually runs the method, in
best_practice. This is where "staff of fire for alchemy", "noted items in
the spell slot", "marks of grace", "best prayer for the boss" etc. live.
equipment[]— item +why(mechanical reason) +source.techniques[]— named technique +why+source.- Every line carries a
source: an OSRS wiki page, orresearched <date>for a fact not yet documented on the wiki — aresearchedflag is a TODO: a follow-up issue must land the proper citation. - The translator MUST adopt the best-practice setup by default. Deviating
requires
improvised: truein the translation header with a reason.
Translation contract (agent -> client)
When an agent picks up an entry to build a script:
- Read
state_machine→ build the client's state machine 1:1 (same state names, same transition conditions). - Walk
actions[]in order; map eachverbusing the client's mapping table indocs/action-grammar.md(DreamBot column, Microbot column, ...). - Apply
run_controlpacing andbreakpolicy verbatim. - Apply every
anti_banhint; the agent may add humanisation but must never remove a codex-mandated one. - Emit a
translationblock in the generated script header: codexid,version, client name, and any verb the agent had to improvise (flaggedimprovised: true).
If a verb has no mapping for the target client, the agent MUST mark it
improvised: true and leave a TODO(client) — never silently invent
behaviour.