Skip to content

feat(langchain): add Stagehand code-mode MCP example - #2629

Open
shrey150 wants to merge 2 commits into
shrey/stg-2765-codemode-crewaifrom
shrey/stg-2765-codemode-langchain
Open

feat(langchain): add Stagehand code-mode MCP example#2629
shrey150 wants to merge 2 commits into
shrey/stg-2765-codemode-crewaifrom
shrey/stg-2765-codemode-langchain

Conversation

@shrey150

@shrey150 shrey150 commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Why

The code-mode MCP should be proven through framework-native clients before the package is published. This layer ports the LangChain Deep Agents draft beside the canonical Stagehand implementation so it can test the exact local build without waiting for package publication.

Stack

  1. #2597 — private package and tool-free MCP host
  2. #2619code_execute, executor, configuration, and runtime tests
  3. #2620 — canonical skill, reference, generated exports, and loading checks
  4. #2626 — Vercel AI SDK adapter and smoke flows
  5. #2627 — Mastra adapter and smoke flows
  6. #2628 — CrewAI adapter and smoke flows
  7. This PR — LangChain Deep Agents adapter and smoke flows

What changed

  • adds a private package-local LangChain Deep Agents example
  • launches the canonical compiled Stagehand MCP through MultiServerMCPClient
  • keeps one explicit client.session("stagehand") open across discovery and the complete agent invocation
  • exposes exactly code_execute and supplies the canonical Stagehand skill as the system prompt
  • inherits both local and Browserbase configuration, including the optional project identifier
  • adds a dedicated local-browser CI smoke job with Python 3.12

The explicit session is the important lifecycle choice: LangChain's convenience get_tools() path can create fresh stdio sessions per call, which would also create fresh browsers and lose prior page state.

E2E Test Matrix

Command / flow Observed output Confidence / sufficiency
Canonical integrations build 4 build tasks passed and rebuilt dist/codemode/stdio-server.mjs. Confirms the example exercised the exact local MCP build under review.
ruff format --check and ruff check over the Python example Both files were formatted and all checks passed. Confirms the adapter and smoke satisfy Python formatting and static lint rules.
LangChain MCP smoke with STAGEHAND_BROWSER=local code_execute ran twice in one explicit session; page identity, title, and DOM marker persisted. Proves discovery, execution, persistent state, and cleanup with a real local browser.
LangChain MCP smoke with STAGEHAND_BROWSER=browserbase code_execute ran twice against the same remote page and retained its DOM marker and title. Proves Browserbase configuration reaches the canonical child and the remote browser is reused.
Real Deep Agent with an OpenAI-compatible model and Browserbase startup The agent made two code_execute calls, retained the same remote page and marker, and returned DEEP_AGENT_PERSISTENCE_PASS. Proves the real model loop, explicit LangChain MCP session, canonical guidance, and Browserbase work together.
Process cleanup audit A matching stdio child existed during each flow and the final matching-child count was zero. Confirms the explicit session owns and closes its MCP child.

Changeset

None. This adds a private example and test surface without changing a published package.


Summary by cubic

Adds a LangChain Deep Agents example that runs the Stagehand code-mode MCP via stdio and keeps one explicit session so code_execute calls share the same browser state. Includes a Python smoke test and a CI job that verifies persistence with a local browser.

  • New Features

    • Adds a private langchain Deep Agents example that launches the compiled stdio server and exposes only code_execute.
    • Uses one explicit client.session("stagehand") across discovery and the full agent run to preserve browser state.
    • Inherits local/Browserbase config (STAGEHAND_BROWSER, BROWSERBASE_API_KEY, optional BROWSERBASE_PROJECT_ID).
    • Loads the Stagehand V4 skill from SKILL.md as the agent system prompt.
    • Adds a Python 3.12 smoke test and a CI workflow job that checks page/title/marker persistence with the local browser.
  • Dependencies

    • Adds example-only Python deps: deepagents, langchain-mcp-adapters, langchain-openai, mcp.

Written for commit d57bce1. Summary will update on new commits.

Review in cubic

@changeset-bot

changeset-bot Bot commented Aug 6, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: d57bce1

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@socket-security

socket-security Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedpypi/​deepagents@​0.7.598100100100100
Addedpypi/​mcp@​1.29.099100100100100
Addedpypi/​langchain-openai@​1.4.1100100100100100
Addedpypi/​langchain-mcp-adapters@​0.3.2100100100100100

View full report

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found and verified against the latest diff

Confidence score: 3/5

  • In packages/integrations/examples/langchain/agent.py, the custom child-process env handling appears to replace the full environment instead of layering overrides, which can break MCP startup or drop inherited credentials when callers pass partial values — merge overrides into os.environ before spawning the child.
  • In packages/integrations/examples/langchain/agent.py, STAGEHAND_CODEMODE_SKILL is loaded from SKILL.md at import time, so smoke.py pulls in file I/O and possible missing-file failures even when the skill text is unused — defer this read until runtime (or guard it) so smoke imports stay lightweight and reliable.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/integrations/examples/langchain/agent.py">

<violation number="1" location="packages/integrations/examples/langchain/agent.py:20">
P3: `STAGEHAND_CODEMODE_SKILL` reads SKILL.md at module import time. Since `smoke.py` imports from `agent.py` but never needs the skill string, that file read also runs whenever the smoke is imported, and a missing/misplaced SKILL.md would fail both scripts during import instead of when the agent actually runs. Consider resolving the skill text lazily inside `run_stagehand_agent` (or a small loader) so importing the helpers doesn't perform file I/O or raise.</violation>

<violation number="2" location="packages/integrations/examples/langchain/agent.py:33">
P2: Custom `env` values currently replace the full child environment, which can make the MCP child fail to start or lose credentials when only partial overrides are passed. Merging overrides into `os.environ` keeps default runtime variables while still allowing explicit overrides.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

"pnpm exec turbo run build --filter @browserbasehq/stagehand-integrations"
)

child_env = dict(os.environ if env is None else env)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Custom env values currently replace the full child environment, which can make the MCP child fail to start or lose credentials when only partial overrides are passed. Merging overrides into os.environ keeps default runtime variables while still allowing explicit overrides.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/integrations/examples/langchain/agent.py, line 33:

<comment>Custom `env` values currently replace the full child environment, which can make the MCP child fail to start or lose credentials when only partial overrides are passed. Merging overrides into `os.environ` keeps default runtime variables while still allowing explicit overrides.</comment>

<file context>
@@ -0,0 +1,97 @@
+            "pnpm exec turbo run build --filter @browserbasehq/stagehand-integrations"
+        )
+
+    child_env = dict(os.environ if env is None else env)
+    return MultiServerMCPClient(
+        {
</file context>

REPOSITORY_ROOT / "packages/integrations/dist/codemode/stdio-server.mjs"
)
SKILL_PATH = REPOSITORY_ROOT / "packages/integrations/codemode/SKILL.md"
STAGEHAND_CODEMODE_SKILL = SKILL_PATH.read_text(encoding="utf-8").strip()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: STAGEHAND_CODEMODE_SKILL reads SKILL.md at module import time. Since smoke.py imports from agent.py but never needs the skill string, that file read also runs whenever the smoke is imported, and a missing/misplaced SKILL.md would fail both scripts during import instead of when the agent actually runs. Consider resolving the skill text lazily inside run_stagehand_agent (or a small loader) so importing the helpers doesn't perform file I/O or raise.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/integrations/examples/langchain/agent.py, line 20:

<comment>`STAGEHAND_CODEMODE_SKILL` reads SKILL.md at module import time. Since `smoke.py` imports from `agent.py` but never needs the skill string, that file read also runs whenever the smoke is imported, and a missing/misplaced SKILL.md would fail both scripts during import instead of when the agent actually runs. Consider resolving the skill text lazily inside `run_stagehand_agent` (or a small loader) so importing the helpers doesn't perform file I/O or raise.</comment>

<file context>
@@ -0,0 +1,97 @@
+    REPOSITORY_ROOT / "packages/integrations/dist/codemode/stdio-server.mjs"
+)
+SKILL_PATH = REPOSITORY_ROOT / "packages/integrations/codemode/SKILL.md"
+STAGEHAND_CODEMODE_SKILL = SKILL_PATH.read_text(encoding="utf-8").strip()
+
+
</file context>

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