Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ Long-running, exploratory research with structured outputs and citations.
| [**Market Analysis Demo**](python-recipes/market-analysis-demo) | Flask app that turns a market-research prompt into a streamed report with email delivery. SSE progress + webhook completion. | `Task` `Deep Research` `SSE` `Webhooks` | Python · Flask · Postgres · Resend | [Live](https://market-analysis-demo.parallel.ai) |
| [**Deep Research Notebook**](python-recipes/Deep_Research_Recipe.ipynb) | Interactive Jupyter walkthrough of Deep Research — text + JSON outputs, citations, confidence scores, webhook patterns. | `Deep Research` `Webhooks` | Jupyter · Python | – |
| [**Due Diligence Agent (Deep Agents)**](python-recipes/parallel-deepagents-due-diligence) | Multi-agent DD on LangChain Deep Agents — five Phase-1 subagents + per-competitor Phase-2 fan-out. `parse_basis` for per-field confidence, `previous_interaction_id` for chained follow-ups, disk-backed workpapers. Validated on Rivian: 14 min, 10 Task calls, 33KB cited memo. | `Task` `Search` | Python · LangChain · Deep Agents | [Sample memo](python-recipes/parallel-deepagents-due-diligence/reports/workpapers/rivian-due-diligence-report.md) |
| [**Shopify Due Diligence (Managed Deep Agents)**](python-recipes/parallel-managed-deepagents-due-diligence) | Dated Shopify financial brief and same-thread follow-up using LangSmith-managed Parallel search, with no Parallel API key. | `Search` `MCP` | Python · Managed Deep Agents · LangSmith | [Sample brief](python-recipes/parallel-managed-deepagents-due-diligence/samples/shopify-brief-2026-09-23.md) |

### Identity & Entity Resolution

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# LangSmith personal API key and the workspace to deploy into.
LANGSMITH_API_KEY=
LANGSMITH_WORKSPACE_ID=

# The agent runs on openai:gpt-5.5 (set in agent.py). `mda deploy` uploads this
# key to the deployment as a secret.
OPENAI_API_KEY=

# Optional, for run_hosted.py: the Agent Server URL printed by `mda deploy`.
LANGGRAPH_URL=

# No Parallel account or Parallel API key is needed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.env
.env.*
!.env.example
.venv/
.mda/
__pycache__/
*.py[cod]
.DS_Store
21 changes: 21 additions & 0 deletions python-recipes/parallel-managed-deepagents-due-diligence/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2025 Parallel Web Systems

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
149 changes: 149 additions & 0 deletions python-recipes/parallel-managed-deepagents-due-diligence/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
# Shopify due diligence with managed Parallel search

This is a small [Managed Deep Agents](https://docs.langchain.com/langsmith/python/managed-deep-agents-overview) example. Managed Deep Agents is LangSmith's way of hosting an agent for you: you write a few files describing the agent, run one command, and LangSmith runs it in the cloud.

This agent researches Shopify. You give it a date, it searches the web with Parallel (managed by LangSmith), and it hands back a sourced due diligence brief. You can keep asking follow-up questions in the same chat. Every search it runs shows up in LangSmith, including the URLs and excerpts it got back, so you can check its work.

By the end you'll have the agent running in your LangSmith account and you'll be chatting with it in the browser. You don't need a Parallel account or API key. The whole search integration is one server entry in [`tools/mcp.py`](tools/mcp.py):

```python
mcp = define_mcp(
servers={
"Parallel": {
"transport": "http",
"url": "https://api.smith.langchain.com/v1/managed-tools/servers/parallel/mcp",
},
},
)
```

LangSmith handles the Parallel credentials and runs the search for you. Parallel search is free during the [Managed Deep Agents public beta](https://www.langchain.com/blog/langsmith-managed-deep-agents-whats-new). The server gives the agent one tool, `Parallel__parallel_web_search`, which returns ranked URLs with excerpts that match the query. The agent cites those excerpts, and when it can't find something it says so instead of guessing. It only ever sees excerpts, so it won't pretend it read a full filing.

## What you need

- Python 3.11 or newer and [uv](https://docs.astral.sh/uv/getting-started/installation/).
- A [LangSmith](https://smith.langchain.com/) workspace on US Cloud, on the Plus plan or higher, with Managed Deep Agents access. Cloud deployment isn't included in the free Developer plan. See [LangSmith pricing](https://docs.langchain.com/langsmith/pricing-plans).
- An [OpenAI API key](https://platform.openai.com/api-keys). The agent runs on `openai:gpt-5.5`, which is already set in [`agent.py`](agent.py), so you don't have to pick a model.

## 1. Clone the repo

```sh
git clone https://github.com/parallel-web/parallel-cookbook.git
cd parallel-cookbook/python-recipes/parallel-managed-deepagents-due-diligence
uv sync --frozen
cp .env.example .env
```

## 2. Fill in `.env`

You need three values. They let the `mda` command line tool deploy the agent into your LangSmith account and give the hosted agent your OpenAI key.

**`LANGSMITH_API_KEY`**

1. Go to [smith.langchain.com](https://smith.langchain.com) and sign in (or sign up with Google, GitHub, or email).
2. Open [**Settings**](https://smith.langchain.com/settings), then **API Keys**.
3. Create a **personal** API key (not a service key) and copy it. LangSmith only shows it once.

**`LANGSMITH_WORKSPACE_ID`**

1. Still in [**Settings**](https://smith.langchain.com/settings), open **General**.
2. Copy the **Workspace ID**.

**`OPENAI_API_KEY`**

Paste your OpenAI API key. When you deploy, `mda` uploads it to the hosted agent as a secret.

Your `.env` should look like this:

```sh
LANGSMITH_API_KEY=lsv2_pt_...
LANGSMITH_WORKSPACE_ID=...
OPENAI_API_KEY=sk-...
```

Don't worry, `.env` is gitignored.

To try the agent locally before deploying, run `uv run mda dev`. It opens Studio with managed Parallel search enabled, without creating a cloud deployment. This recipe pins `managed-deepagents==0.8.0`, which includes the local managed-tool identity fix.

## 3. Deploy it to LangSmith

```sh
uv run mda deploy
```

This packages up the project and creates a deployment called `shopify-due-diligence` in your workspace. It also uploads the agent's prompt, [`instructions.md`](instructions.md), to LangSmith's Context Hub. It takes a few minutes. When it's done, it prints a dashboard URL.

## 4. Chat with it in Studio

Studio is LangSmith's chat window for deployed agents. Open the dashboard URL from the deploy, click **Connect → Studio**, open **Chat**, pick **shopify-due-diligence**, and turn on **Show tool calls** so you can watch the searches happen.

Start a new thread and send:

```text
Prepare a Shopify due diligence brief as of today.
```

The agent resolves "today" using the current UTC date and shows the exact date in the brief. You can also give an explicit date, like `2026-09-23`. If you leave the date out, it asks for one. You'll get a brief that names the latest reported quarter and the 90-day window it looked at, puts a dated source link next to each claim, and lists anything it couldn't verify. If one of those gaps matters to you, just ask it to go look.

Then, in the same thread, try:

```text
How does subscription versus merchant-services growth affect Shopify's margins in that quarter?
```

It sticks with the same quarter from the brief and knows "merchant services" means Shopify's **Merchant solutions** revenue line. It'll search again if it needs more, and it keeps the reported numbers separate from its own margin analysis.

Want to see what a run looks like first? The [saved sample](samples/shopify-brief-2026-09-23.md) has a brief and follow-up from September 23, 2026, along with the run IDs and the gaps it found.

## 5. Check the search evidence

A trace is LangSmith's step-by-step record of a run. From Studio, open the run's trace and expand a **Parallel__parallel_web_search** call. The inputs show the queries the agent sent, and the output shows the URLs and excerpts it got back.

Pick a number from the brief, click its source link, and find the matching excerpt in the tool output. That way you're checking the evidence itself, not just taking the agent's word for it.

## Make it your own

- **Change what it researches or how the brief looks:** edit [`instructions.md`](instructions.md) and run `uv run mda deploy` again. Parallel's [Search best practices](https://docs.parallel.ai/search/best-practices) are worth a read for writing good search objectives and queries.
- **Use a different model:** change `model` in [`agent.py`](agent.py). Any tool-calling model from LangChain's [supported models list](https://docs.langchain.com/oss/python/deepagents/models#supported-models) works. This project only installs `langchain-openai`, so another provider also needs its integration package and API key.

## Optional: run it from the terminal

If you'd rather skip Studio, [`run_hosted.py`](run_hosted.py) talks to the deployed agent directly. Add `LANGGRAPH_URL` to `.env`. That's the deployment's Agent Server URL, which you'll find in the deploy output and on the dashboard. Then run:

```sh
uv run --env-file .env python run_hosted.py "Prepare a Shopify due diligence brief as of today."
```

It prints `Thread: ...` and then the answer. Pass that thread ID to keep the conversation going:

```sh
uv run --env-file .env python run_hosted.py --thread THREAD_ID "How does subscription versus merchant-services growth affect Shopify's margins in that quarter?"
```

The runner sends your personal key with `x-auth-scheme: langsmith`, using Studio's authentication route to supply the person identity that managed tools need.

## Files

| File | What it does |
| --- | --- |
| `agent.py` | Names the agent and sets its model |
| `instructions.md` | The system prompt: brief layout, sourcing rules, date window, and how to handle follow-ups |
| `tools/mcp.py` | Hooks up the managed Parallel MCP server |
| `identity.py` | Requires LangSmith auth, which managed search needs |
| `run_hosted.py` | Optional terminal client for the hosted agent |
| `samples/` | A saved brief and follow-up |

## Troubleshooting

- **Deploy fails with 401 or 403**: check that your API key is from a workspace on the Plus plan or higher, and that `LANGSMITH_WORKSPACE_ID` matches that workspace.
- **Deploy says the OpenAI key is missing**: make sure `OPENAI_API_KEY` is set in `.env`.
- **`user-owned connections require a person principal`**: the request showed up as a service caller. Use Studio, or `run_hosted.py` with a personal API key.
- **No `Parallel__parallel_web_search` calls in the trace**: make sure `identity.py` is still in the project. Without a signed-in caller, the agent skips managed MCP servers.
- **Studio says your token is invalid after a redeploy**: reload Studio.
- **Deploy asks about Context Hub edits**: someone changed the prompt in LangSmith since your last deploy. Decide whether to keep their edits or replace them with your `instructions.md`.

For more on deploying, check out the [Managed Deep Agents docs](https://docs.langchain.com/langsmith/python/managed-deep-agents-overview) and the [CLI reference](https://docs.langchain.com/langsmith/python/managed-deep-agents-cli).

## License

[MIT](LICENSE).
28 changes: 28 additions & 0 deletions python-recipes/parallel-managed-deepagents-due-diligence/agent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""Shopify research, hosted by Managed Deep Agents."""

from datetime import datetime, timezone

from langchain.agents.middleware import ModelRequest, dynamic_prompt
from langchain_core.messages import SystemMessage
from managed_deepagents import define_deep_agent


@dynamic_prompt
def current_date(request: ModelRequest) -> SystemMessage:
"""Refresh the date on every model request without replacing managed instructions."""
today = datetime.now(timezone.utc).date().isoformat()
return request.system_message.model_copy(
update={
"content": [
*request.system_message.content_blocks,
{"type": "text", "text": f"Current date (UTC): {today}."},
]
}
)


agent = define_deep_agent(
name="shopify-due-diligence",
middleware=[current_date],
model="openai:gpt-5.5",
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""Require LangSmith authentication. Managed Parallel search needs an authenticated caller."""

from managed_deepagents import auth, define_identity

identity = define_identity(auth=auth.langsmith_api_key())
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
You help a financial analyst research Shopify. You search the web with
LangSmith-managed Parallel search and reply in the conversation. This is an
example of researching one company. It is not a trading or valuation service.

## How to search

- Start every new brief by calling Parallel__parallel_web_search.
- Prefer Shopify's own sources: filings, earnings releases, investor materials,
and official announcements. Use reputable secondary sources for context only
when you need them, and say where they came from.
- Only use what search returns. Don't answer from memory, and don't use shell
commands or raw HTTP requests instead of search.
- Search gives you URLs and excerpts. It does not guarantee the full document.

Each search has an objective and keyword queries:

- **Objective:** one short, self-contained sentence describing the evidence you
need. Name Shopify Inc., say which sources you prefer, and include the
relevant dates. For anything time-bound, include the brief's exact date
window in the objective every time.
- **Queries:** 1 to 3 different short keyword queries, usually 3 to 6 words
each. Keep instructions and source preferences out of the queries. Don't use
`site:` unless you have a reason to.
- Group related angles into one search. Use separate searches for unrelated
questions.
- When the results leave a gap, run a focused search for that gap.

## Dates

- Use the as-of date the user gives you. Resolve "today" using the current UTC
date supplied with the system instructions, and show the resolved date as
YYYY-MM-DD in the brief. An explicit date takes precedence. If the request
supplies neither a date nor "today", ask.
- The 90-day window is the 90 calendar days ending on the as-of date, counting
both ends. Show the first and last date.
- Only use information published on or before the as-of date.
- Use the latest quarter Shopify has actually reported. A scheduled earnings
date or an analyst estimate doesn't count.
- An event date and a source's publish date can differ. Say which one the
evidence shows.
- An announcement or a rollout in progress doesn't mean the thing is fully
available. Report the status the source gives.

## Evidence rules

- Every important claim needs support from an excerpt search actually
returned. A promising title or URL isn't enough.
- If the excerpts don't establish a figure, date, relationship, or risk, search
again. If you still can't find it, say it wasn't verified in the returned
excerpts. Never guess.
- Not finding something doesn't prove it wasn't disclosed. It also doesn't tell
you a product's reporting or legal status, or that a figure can't be
calculated. You need returned evidence that says so. Use this careful wording
everywhere, including when you describe what a development means.
- Keep what management says separate from reported results, and label your own
analysis as analysis.

## Initial brief

Aim for 600 to 900 words, in this order:

1. **Header:** the as-of date, the latest reported quarter, and the 90-day
window's start and end dates.
2. **Financial snapshot:** quarterly revenue and year-over-year growth, gross
profit, operating profit, operating cash flow, free cash flow, and cash at
the balance-sheet date. Mention net income separately if it's relevant,
including any big investment gains that change what it means.
3. **Management guidance:** the period it covers, when it was given, and what
management actually said. Guidance is a forecast, not a result.
4. **Three important developments** from inside the window. Give each one's
date and source, and say why it matters financially. If you can only verify
fewer than three, say so.
- Don't repeat numbers from the financial snapshot.
- An earnings release and its guidance count as one development.
- Look beyond the newsroom: search partner, enterprise, and product
announcements too.
- Don't count commentary or an earnings-calendar notice just to fill a slot.
5. **Key risks and evidence gaps:** keep risks Shopify disclosed separate from
risks you're inferring.

## Numbers and sources

- Put a dated source link next to each claim it supports.
- Always state the period, currency, and units.
- Keep these pairs clearly separate: quarter-only vs. year-to-date cash flow,
GAAP vs. non-GAAP, cash and cash equivalents vs. investments, and revenue vs.
gross merchandise volume (GMV).
- The first time you use a non-GAAP measure, label it as non-GAAP and use the
source's definition. This includes constant-currency growth, adjusted net
income, free cash flow, and FCF margin.
- Before comparing cash flow across periods, search for any changes in how it's
presented or accounted for. If a disclosed change affects the comparison,
explain it before crediting growth or margin gains to the business. If you
can't confirm the comparison is apples to apples, say so.
- If you only get part of an accounting note, report what you verified and say
what's missing.
- When you calculate something, show the inputs and the math. Never make up a
figure Shopify didn't disclose.

## Follow-up questions

- Stick with the as-of date, quarter, and context already in this conversation.
- Search again if you need more evidence.
- Shopify's two revenue lines are Subscription solutions and Merchant
solutions. If the user says "merchant services", they mean Merchant
solutions.
- Explain how revenue mix can affect gross margin, and how operating leverage
can affect operating margin and free cash flow margin. Keep those measures
separate.
- Only calculate a gross margin for each revenue line if the returned evidence
gives you both the revenue and the cost for that line.
- Label cause-and-effect explanations as analysis, and cite the evidence behind
them.

## Out of scope

You don't need sandbox execution, file generation, memory across threads, or
extra agents. Don't claim you read complete filings, and don't make investment
recommendations the evidence doesn't support.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[project]
name = "shopify-due-diligence-demo"
version = "0.1.0"
description = "A Shopify research example using Managed Deep Agents and managed Parallel search."
requires-python = ">=3.11"
dependencies = [
"langchain>=1.3.15",
"langchain-openai>=1.6.5",
"langgraph-sdk>=0.4.5",
"managed-deepagents==0.8.0",
]
Loading
Loading