feat: native persona-driven website navigation#2
Open
lfiaschi wants to merge 1 commit into
Open
Conversation
Add a first-class API for letting a sampled persona browse a real website and choose its own next action, turning the `persona-browse` skill (a manual recipe) into reproducible, testable code. `PersonaNavigator` reads each page (text + optional screenshot), reacts in character, and picks ONE action from the real on-page options — AudienceKit never guesses the next move with heuristics. The browser stays injected via the `Browser` protocol (the same dependency-light philosophy as the pluggable LLM backends), so callers wire in agent-browser, Playwright, or a fixture. - audiencekit/browse.py: PageView, BrowseAction, PersonaStep, PersonaNavigator, Browser protocol, build_browse_prompt, run_browse_session, extra_fields for domain-specific reaction fields, and a `boundary` hook to stop at out-of-scope payment/verification walls. - Export the new surface from the package root. - tests/test_browse.py: 7 network-free tests using an injected backend + a fixture browser. - Document the programmatic path in the persona-browse skill and README. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
AudienceKit can already make a persona react to a static stimulus (
SyntheticPanel.run_survey). What it can't do programmatically is let that persona browse — read a live page, decide what matters, and pick its own next move. Today that lives only in thepersona-browseskill: a manual narration recipe an agent follows by hand. That's great for a one-off walkthrough but can't be scripted, parallelised, cached, or tested, so it can't back a real study (e.g. 50 personas × 14 sites, structured output, reproducible).This PR closes that gap by making persona-driven navigation a first-class, testable API — while keeping the move-by-move decision genuinely in the persona's hands rather than in heuristic glue code.
Why this shape
Browserprotocol, so callers wire inagent-browser, Playwright, Selenium, or a fixture. Zero new dependencies.render_persona,parse_json_response, andmake_backend(with vision) the survey path already uses.How I want to use it
I'm running a synthetic competitive-UX study: sample a fixed GSS-grounded panel, then send each persona through real meal-kit checkout flows. I need each shopper to follow their own path — a price-sensitive shopper heads for pricing and may bail at sticker shock; a health-oriented one digs into the menu — and to record, per step, what they noticed, how the price felt, where trust moved, and whether they left.
PersonaNavigator+run_browse_sessiongive exactly that, withextra_fieldsfor the domain-specific reactions (price perception) and aboundaryhook to stop at payment/verification walls that are out of scope.What's added
audiencekit/browse.pyPageView,BrowseAction,PersonaStep— small frozen dataclasses (survey.py style).PersonaNavigator—.step(page, actions, history=...)→ in-character reaction + chosen action;extra_fields=to request domain-specific fields; vision via the page screenshot.Browserprotocol +run_browse_session(nav, browser, url, max_steps=, boundary=)driver loop.build_browse_prompt,LEAVE,DEFAULT_REACTION_FIELDS.__all__).tests/test_browse.py— 7 network-free tests (injected backend + fixture browser): action resolution, leave, unparseable/unknown-choice fallback, extra fields, full session drive, boundary stop.skills/persona-browse/SKILL.md(with a sampleagent-browseradapter) and a "Website Analysis" update inREADME.md.Example
Test plan
pytest -q→ 35 passed (7 new, 28 existing unchanged).🤖 Generated with Claude Code