Skip to content

feat(connector): one-call setup() for any agent#172

Closed
risjai wants to merge 1 commit into
masterfrom
feat/connector-setup
Closed

feat(connector): one-call setup() for any agent#172
risjai wants to merge 1 commit into
masterfrom
feat/connector-setup

Conversation

@risjai

@risjai risjai commented May 21, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • New rewind_agent.connector.setup(name=...) context manager — one call to compose ExplicitClient.session() + intercept.install() in the right order.
  • Eliminates the silent-no-op trap where intercept records nothing because no session is active (the most common Tier-1 integration mistake).
  • Replaces ~280 LOC of bespoke session-management code per integrator with a single with block.
  • Bumps rewind-agent 0.16.0 → 0.16.1.

Why

PR #171 shipped docs that route framework integrators to intercept.install() for HTTP-shaped LLM clients. But the working pattern requires three things in the right order: open an ExplicitClient session (sets _session_id/_timeline_id contextvars) → call intercept.install(predicates=...) → tear both down on exit. Get the order wrong and intercept records nothing — silently, because record_llm_call returns None when no session is active (explicit.py:276-278).

connector.setup() is the blessed one-liner. ~150 LOC including docstrings; the actual orchestration is a dozen lines. Every Tier-1 integration becomes:

import rewind_agent
with rewind_agent.connector.setup(name="my-agent"):
    run_agent_loop()

What's in the API

  • Kill switch: REWIND_ENABLED=0 makes setup() a true no-op (yields None, no HTTP, no install).
  • Configurable hosts: REWIND_LLM_HOSTS=a.example,b.example (comma-separated) extends the strict-by-default LLM provider list. Kwargs override env.
  • Server URL: REWIND_URL env var or base_url= kwarg.
  • Replay-aware: when REWIND_SESSION_ID + REWIND_REPLAY_CONTEXT_ID are set (runner-subprocess pattern from docs/runners.md), setup() skips creating a fresh session and lets intercept.install() attach to the existing replay context. No phantom sessions during runner-driven replays.
  • Idempotent intercept: doesn't uninstall on exit if the caller already had intercept installed at entry — composes cleanly with operator-level setup.
  • Non-HTTP escape hatch: yields the underlying ExplicitClient for callers that need record_llm_call/record_tool_call on custom transports (gRPC, in-process LLMs).

Tests

12 tests in python/tests/test_connector.py covering:

  • Kill switch (env + kwarg)
  • Session start/end via mock HTTP server
  • thread_id and metadata propagation
  • Replay-dispatch env detection (full vs partial env vars)
  • Host predicates from kwarg, env (with whitespace/empty handling), and defaults
  • Idempotent intercept install (no uninstall when caller pre-installed)
  • Public module export

Full python suite: 488 passed, 1 skipped (the 1 skip is unrelated env-conditional).

Why ship in rewind_agent rather than as a separate package

The original plan considered shipping this as an external connector package (one per org). After review, the abstraction is generic: nothing in it is specific to a particular gateway, app, or framework. Every Tier-3 integrator would write the same shape. Keeping it in the SDK gives every consumer one blessed pattern, eliminates the silent-no-op pitfall, and avoids per-team copy-paste drift.

This is meaningfully smaller than the FrameworkAdapter Protocol Santa Method review rejected from the original plan: no new type, no Store/Recorder leak, no entrypoint discovery, no Protocol — just one @contextmanager function that calls two existing public APIs in the right order.

Test plan

  • cd python && pytest tests/test_connector.py -v — 12/12 green.
  • cd python && pytest --ignore=tests/e2e — full suite green (488 passed locally).
  • Manual smoke: with rewind_agent.connector.setup("smoke"): httpx.post("https://api.openai.com/v1/chat/completions", ...) against a running rewind web server; confirm session shows up via rewind show latest.
  • Replay smoke: set REWIND_SESSION_ID + REWIND_REPLAY_CONTEXT_ID in a subshell; confirm setup() does NOT create a phantom /api/sessions/start call.
  • After merge: publish to PyPI via python/scripts/publish-pypi.sh.

Follow-up

A small docs PR will update docs/hdk.md Tier 1 to recommend rewind_agent.connector.setup() as the one-liner. Deferred to a separate PR because that file lands in #171, which hasn't merged yet.

🤖 Generated with Claude Code

…t in one block

Adds rewind_agent.connector.setup(name=...): a context manager that
composes ExplicitClient.session() + intercept.install() in the right
order so callers don't have to remember the dance. Eliminates the
silent-no-op trap where intercept records nothing because no session
is active — the most common Tier-1 integration mistake.

Behavior
- Wraps the with-block in a fresh session, sets _session_id and
  _timeline_id contextvars, installs HTTP intercept, yields the
  ExplicitClient for non-HTTP record_* paths inside the block, and
  cleans up on exit.
- Honors REWIND_ENABLED=0 as a true zero-overhead kill switch
  (yields None, no install, no HTTP).
- Honors REWIND_URL (default 127.0.0.1:4800) and REWIND_LLM_HOSTS
  (comma-separated) for env-based config; kwargs override env.
- When REWIND_SESSION_ID and REWIND_REPLAY_CONTEXT_ID are set
  (runner-subprocess pattern from docs/runners.md), skips creating a
  fresh session and lets intercept.install() attach to the existing
  replay context — no phantom sessions during runner-driven replays.
- Idempotent intercept install: doesn't uninstall on exit if the
  caller already had it installed at entry.

Implementation
- python/rewind_agent/connector.py — ~150 LOC including docstrings.
- python/rewind_agent/__init__.py — re-exports the connector module
  in __all__ and updates the package docstring.
- python/tests/test_connector.py — 12 tests covering kill switch
  (env + kwarg), session lifecycle, replay-dispatch detection, host
  predicates from env / kwarg / defaults, idempotent install, and
  public export.

Version
- python/pyproject.toml + __init__.py bumped 0.16.0 → 0.16.1 per
  CLAUDE.md Track 2 (python/ files changed; 0.16.0 is on PyPI).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@vercel

vercel Bot commented May 21, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
rewind Ready Ready Preview, Comment May 21, 2026 3:12pm

@risjai

risjai commented May 21, 2026

Copy link
Copy Markdown
Collaborator Author

Combined into #171 — same code, plus docs/hdk.md updated to lead Tier 1 with the new connector.setup() API. Single PR is easier to review and ship together.

@risjai risjai closed this May 21, 2026
@risjai
risjai deleted the feat/connector-setup branch May 21, 2026 15:19
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.

1 participant