Skip to main content
Glama

OfferUpBot

OfferUpBot ist die OfferUp-Ausführungsschicht für externe Agents. Agents erkennen Artikel, wählen Preise aus, verfassen die Anzeigentexte und entscheiden über die Antwort. OfferUpBot übernimmt OfferUp-Zugriff, Anmeldestand, Persistenz, Browser-Arbeit, Wiederholungen, Duplikat-Verhinderung und die externe Verifizierung.

Guide für Agents

Agents, die ohne Konversationshistorie arbeiten, starten mit AGENTS.md. Für die direkte OfferUp-Ausführung gilt skills/operating-offerupbot/SKILL.md; für den End-to-End-Besitz physischer Artikel gilt skills/operating-seller-operator/SKILL.md; für folgenreiche Bildauswertung gilt skills/inspecting-visual-evidence/SKILL.md. Jede Skill lädt weiteres Material erst nach, wenn die Aufgabe es erforderlich.

Laufzeit-Entscheidung

Die Standard-Schnittstelle ist On-Demand-MCP-stdio.

agent launches OfferUpBot
        ↓
MCP tools execute against shared SQLite state and browser profile
        ↓
agent disconnects
        ↓
OfferUpBot exits

Der Zustand bleibt in SQLite und im dedizierten OfferUp-Browserprofil erhalten. Der Standardprozess startet keinen Scheduler, keinen HTTP-Listener und keinen Hintergrund-Monitor.

Der stetige monitor-Modus ist optional und standardmäßig abgeschaltet. run:due führt einen ausdrücklichen Nachhol-Lauf durch und endet danach.

Anforderungen

  • macOS mit installiertem Google Chrome für authentifizierte Vorgänge

  • Node.js 22 oder aktueller

  • pnpm

Docker, eine externe Datenbank, Redis oder ein separat verwalteter Laufzeitdienst werden nicht benötigt.

Installation und Build

git clone https://github.com/yinkev/OfferUpBot.git
cd OfferUpBot
pnpm install
pnpm build

Starte den Einstiegspunkt für die Entwicklungsumgebung:

pnpm mcp

Starte den gebauten Einstiegspunkt:

pnpm start

Das Standard-Datenverzeichnis liegt in:

~/.offerupbot/
├── state.sqlite
├── browser-profile/
└── agents.json          # only after restricted agents are created

Es kann über OFFERUPBOT_DATA_DIR gesetzt werden, falls eine solche Trennung erforderlich ist.

OfferUp-Anmeldung

pnpm auth:login

Ein dediziertes Chrome-Fenster öffnet sich. Gib deine Zugangs direkt bei OfferUp ein. Die Anmeldung wird erst akzeptiert, wenn die authentifizierte Kontenabfrage von OfferUp eine echte Konto-ID liefert. Zugangsdaten werden nicht über den Chat angefordert oder in SQLite gespeichert.

MCP-Konfiguration

Nach pnpm build richtest du den Agent-Host auf den gebauten stdio-Einstiegspunkt aus:

{
  "mcpServers": {
    "offerupbot": {
      "command": "node",
      "args": [
        "/absolute/path/to/OfferUpBot/dist/src/index.js"
      ],
      "env": {
        "OFFERUPBOT_DATA_DIR": "/absolute/path/to/.offerupbot"
      }
    }
  }
}

Ohne Agent-Token läuft der lokale stdio-Prozess als vertrauensvoller Voll-Operator.

Erstelle eine eingeschränkte Identität, wenn der Agent nur begrenzte Befehle erhalten soll:

pnpm agent:create -- \
  --id research-agent \
  --name "Research Agent" \
  --permissions market.read,events.read,watch.manage

Lege das dort erzeugte Token in der MCP-Umgebung des Agents mehr als OFFERUPBOT_AGENT_TOKEN fest. OfferUpBot speichert ausschließlich seinen SHA-256-Hash.

Agents-Werkzeuge

Werkzeug

Verwendungszweck

Berechtigung

offerup.health

Lokale Laufzeit- und Cache-Session-Gesundheit

keine

offerup.auth_status

OfferUp-Accountidentität und -fähigkeiten überprüfen

account.read

offerup.research_market

Suche mit validierten OfferUp-Filtern

market.read

offerup.inspect_listing

Vollständige Inserats-Information; optional geordnete Fotos als als download_photos länger lesbare lokale Dateien zwischenspeichern

market.read

offerup.watch_market

Watch erstellen, anzeigen, pausieren, fortsetzen, löschen oder ausführen

watch.manage

offerup.run_due

Jeden überfälligen Watch einmal ausführen

watch.manage

offerup.next_events

Dauerhafte Ereignisse lesen und bestätigen

events.read

offerup.sync_listings

Aktive, archivierte und gespeicherte Account-Zustände synchronisieren

account.read

offerup.sync_inbox

Synchronisierung der E-Mail-Conversations und Käufer-Message-Änderungen

account.read

offerup.get_thread

Eine gesamte Konversation samt Inserats-Kontext abrufen

account.read

offerup.send_message

Eine idempotente, extern verifizierte Nachricht senden

message.send

offerup.validate_listing

Den aktuellen Consumer-Inseratsvertrag validieren

keine

offerup.publish_listing

Die Inserat veröffentlichen und verifizieren

listing.publish

offerup.update_listing

Gültige Felder bearbeiten und verifizieren

listing.update

offerup.close_listing

Als verkauft markieren oder Archivieren, danach den Konto-Zustand überprüfen

listing.close

Start bei skills/operating-offerupbot/SKILL.md; das danebenliegende REFERENCE.md und WORKFLOWS.md enthalten die genauen Vertragsbedingungen und Abläufe.

Seller-Operator-Werkzeuge

Üben der Ausführungsschicht liegt eine zweite MCP-Oberfläche für Agents, die physische Artikel vollständig führen: ÄhnlicheInzahl aus 30 seller.*-Werkzeugen für Fall-/Artikelaufnahme, Fotos and proof-of-origin-tracked documents, OCR/deterministic extraction and identity selection, evidence-sufficiency-Klärungen, competitor research, pricing and disposition decisions, verified listing drafts with verified publish/close, buyer classification, offers, exclusive reservations, conflict-checked appointments with idempotent reminders, Run through a due-task operator loop plus Handoff-Aufzeichnung, and lifecycle metrics implement.

Berechtigungen: seller.read (Lesezugriffe), seller.write (Schreibvorgänge im Domainbereich, für publish/close zusätzlich listing.publish/listing.close), seller.communicate (Buyer-Aktionen). Messages nehmen weiterhin den verified offerup.send_message-Weg. Start bei skills/operating-seller-operator/SKILL.md; REFERENCE.md und WORKFLOWS.md daneben enthalten die Beweis-, Markt-, Käufer- und Lifecycle-Leitlinien.

IDs und Schreibvorgänge

OfferUp verwendet zwei unterschiedliche Inserat-Identifikatoren:

  • listing_id: UUID für öffentliche Details, Konversationen, Überprüfung und Edit-Mutationseingabe.

  • item_id: numerische Verkäufer-Bestands-ID für /selling, Verkauf-Markieren und Archivieren.

Jedes folgenreiche Werkzeug benötigt einen dauerhaften Idempotenzschlüssel. Benutzen sie nach Timeout oder Absturz denselben Schlüssel. Wird der Schlüssel verändert, kann ein Recovery-Versuch in eine dazu doppelte externe Aktion umschlagen.

Explizite Scheduler-Modi

Alle überfälligen Whatch einmal ausführen und beenden:

pnpm run:due

Kontinuierliches Watch-Scheduling läuft im Vordergrund nur, wenn bewusstes Polling erforderlich ist:

pnpm monitor

monitor ist niemals von pnpm mcp, pnpm start, Installation oder Anmeldung gestartet. Das Beenden stoppt das Polling. Ein später run:due- oder MCP-offerup.run_due-Call holt aus den gespeicherten Watch-Zuständen nach.

Übergabe-Schnittstelle (opt-in)

pnpm handoff startet eine kleine, nur im Vordergrund sichtbare HTTP-Oberfläche für den einen persönlichen Kontaktpunkt: die Übergabe vor Ort. Er listet unter GET / fällige/offene Handoff-Karten auf (Käufer, zugesagter Preis, Termin, Zubehör, Mängel, Zahlungsmodalität, Ersatzkäufer),in GET /api/handoffs-Expose verfügbar und dokumentiert Ergebnisse über POST /api/handoffs/:itemId/result gegen den eigenen SQLite-Stand.

Er bindet 127.0.0.1 (über OFFERUPBOT_HANDOFF_HOST/OFFERUPBOT_HANDOFF_PORT überschreibbar) und erwartet einen Bearer-Token aus OFFERUPBOT_HANDOFF_TOKEN; oh ne, wird ein Token generiert und beim Start einmalig gedruckt. Wie monitor wird es nie von einer anderen Einheit gestartet: der Standard-Runtime bleibt on-demand MCP stdio ohne Listener.

Fehlersemantik

aden Schreibvorgang ist erst vollständig, wenn dessen Antwort verified: true enthält.

Hinweis auf wichtige Fehlercodes:

  • OFFERUP_SESSION_EXPIRED / AUTH_REQUIRED: complete Anmeldung erfolgt, bevor du fortfahren kann.

  • RESOURCE_BUSY: Ein anderer Prozess hält den Account oder „browser“ in bezirk.####; später mit demselben Idempotenzschlüssel erneut aufrufen.

  • RESOURCE_LOCK_LOST: Nicht davon ausgehen, dass der Schreibvorgang durchgeführt wurde; before dem nächsten Auchtele relevanten Lese- oder Sync-Werkzeug.

  • IDEMPOTENCY_CONFLICT: verändender Schlüssel wurde mit anderen Zielen angetragen; – gleiche den Zustand der Agent.

  • OFFERUP_FILTER_MISMATCH: OfferUp hat einen Filterig Ingen (silent) nicht angegewendet; – close nicht gekränkt.

  • AUTO_CATEGORY_MISMATCH: OfferUp hat eine Kategorie erzwungen, die vom Entwurf abweicht.

  • CATEGORY_PATH_NOT_TERMINAL: der Pfad landein in einer Hauptkategorie statt harm Capwahl finalen Kategorie.

Verifizierung

Routine-Verifikation:

pnpm test
pnpm typecheck
pnpm build

Read-only Live-Akzeptanztes gegen das konfigurierte OfferUp-Profil und die Public-Website:

OFFERUPBOT_LIVE_TESTS=1 pnpm exec tsx --test \
  tests/account/live.test.ts \
  tests/auth/live.test.ts \
  tests/offerup/public/live.test.ts

Sichere abgefangene Write-Contract-Abnahme:

OFFERUPBOT_LIVE=1 pnpm exec tsx --test --test-concurrency=1 \
  tests/messages/live-direct.test.ts \
  tests/listings/live-browser.test.ts \
  tests/listings/live-close.test.ts

Die abgefangenen Runs durchlaufen die aktuellen Nachrichten-, Consumer-Publish-, Edit-, Meds-Upload-, Mark-Sold- und Archiving-Pfade auf der jeweiligen Live-OfferUp-UI, während sie die verifizierten loko Oppositions abhängigen. lokal. Sie kreere, verändern, verkaufen nirgends eine echte Anzeige.

Aktuelle Abnahmegrenze

Der Code, public read, authenticated read, Web-Message-Mutation, Consumer-Publish/Edit-UI-Verträge und Close-Mutation sind implementiert und getestet. Ein begrenzter In-Memory-Agent-Test deckt Research über Publish, Inbox, Message, Update und Close ab.

Ein dafür festgelegter/ ein als auf dem dedicated Abnahme-Konto festgelegter Listing-Lebenszyklus wurde am 2026-08-24 durchlaufen: ein Philips Norelco BG7030/49 wurde mit sechs Fotos veröffentlicht und extern verifiziert, von $60 auf $55 aktualisiert und unter verlorenem Zustand erneut verifiziert, dann im authentifizierten Bestand als UNLISTED archiviert und verifiziert. Der Run machte und schloss zwei reale Fehler: Die Endkategorie-Auswahl öffnete (oder beschädigte?) und Anzeige blieb fälschlich sichtbar: price-only edit das Condition-Feld unverändert.

Die übriggebliebene Echt-Nachricht-Umsetzungs-Tür wurde am selben Tag beantwortet: offerup.send_message sendet ein $50-cash-Angebot über den direkten Adapter, die zurückgegebene Nachricht-ID wurde im genauen Thread noch einmal geholt und der authentifizierte Inbox-Sync hat das Gespräch bestätigt. Darauf reichte der Verkäufer: „Its a pokemon center etb,“, was einen separaten Reasoning-Fehler anzeigt. Das erste Foto identifizierte die Exklusiv-Variante des Pokémon-Centers clearly, der Agent hatte aber das normale ETF bewertet. Direkteches TCGplayer-Preis neben NFT 692949 war ungefähr $120, so sind $50 nur nur ~42 % des Warenwerts—nicht 78 %. Die exactly-once-Write-Acceptance Appl. ; Varianten- sowie Bewertung und Zustimmung kommentierte failed. Die korrigierte Post-Map enthält docs/acceptance/2026-08-24-real-message-send.md.

Beide de signierten consequential-write Transport-Abnahmen sind abgeschlossen. Zukünftige echte Writes immer noch brauchen ein explizite verifiziertes Listing-oder Konversation; wiederholbare dramatic tests bleiben intercepted-intercepted und dürfen keine unge ändern beliebige Konten.

Seller-Operator-Schicht (stand 2026-08)

Oberhalb dieser Ausführungsschicht : des seller-operator system: canonical physical items mit beunruhig aber Provenance-verfolgt Dokumentation, identity resolution, markt/pricing research with disaster-… separation possible real vs live-comps, gated listing release, buyer/offer/reservation/appointment state,(handoff result recording), re-containing case context as instance. Ohne Router geldet es quanto production rtime : ist fully wired : at start all schema be prepared; runtime.runDue() geht einen single-mell pass über watches + seller tasks; account listing sync adds einen time-series of views/chat-prices. Exposed is mit den oben genannten seller.* tools.

Optional integrations (disabled standardmäßig):

  • OFFERUPBOT_READ_ONLY=1 — blockiert jede ergeel-lastige OfferUp-reekswrite (publish/update/close/sent, Interpret).

  • OFFERUPBOT_EBAY_CLIENT_ID/OFFERUPBOT_EBAY_CLIENT_SECRET-keys entsprechend, wenn eBay-Quellen (ask+ sell, official APIs) angeschaltet werden. Ohne them it prepare not available, comps stay empty; nichts wird gescrapt.

  • OCR-Gu-VIA mac » verfügbar (darwin + osascript) bedient…; Fallback = deterministisch-only.

Ergebnisanalysen (src/analytics) berechnen den vollständigen Satz an Metriken für verkaufte und nicht verkaufte Artikel gleichermaßen; Kategorie-Priors aus abgeschlossenen Ergebnissen fließen in Preisgestaltung und Disposition ein (begrenzt, nach Stichprobengröße geschrumpft, in der Entscheidungsbegründung festgehalten). Siehe docs/seller-operator-architecture.md für die Schichtenübersicht und Invarianten, docs/seller-operator-tracker.md für den Build- Status und tests/e2e/seller-operator.test.ts für den kontrollierten Abnahmetest des vollständigen Lebenszyklus (gemockte externe Schreibvorgänge — keine echten Marktplatzänderungen).

Maintenance

ActivityMaintained
ResponsivenessSyncing

Related MCP Connectors