langchain-hyperresearch 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- langchain_hyperresearch-0.1.0/.gitignore +6 -0
- langchain_hyperresearch-0.1.0/LICENSE +21 -0
- langchain_hyperresearch-0.1.0/PKG-INFO +194 -0
- langchain_hyperresearch-0.1.0/README.md +172 -0
- langchain_hyperresearch-0.1.0/langchain_hyperresearch/__init__.py +27 -0
- langchain_hyperresearch-0.1.0/langchain_hyperresearch/_client.py +301 -0
- langchain_hyperresearch-0.1.0/langchain_hyperresearch/py.typed +0 -0
- langchain_hyperresearch-0.1.0/langchain_hyperresearch/retrievers.py +78 -0
- langchain_hyperresearch-0.1.0/langchain_hyperresearch/tools.py +202 -0
- langchain_hyperresearch-0.1.0/pyproject.toml +62 -0
- langchain_hyperresearch-0.1.0/tests/__init__.py +0 -0
- langchain_hyperresearch-0.1.0/tests/unit_tests/__init__.py +0 -0
- langchain_hyperresearch-0.1.0/tests/unit_tests/test_standard.py +35 -0
- langchain_hyperresearch-0.1.0/tests/unit_tests/test_tools.py +241 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Thalient Labs Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: langchain-hyperresearch
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: LangChain integration for Hyperresearch Answers: a cited, quote-checked answer tool, a raw-source search tool and a retriever.
|
|
5
|
+
Project-URL: Homepage, https://hyperresearch.ai/answers
|
|
6
|
+
Project-URL: Documentation, https://hyperresearch.ai/docs/answers/langchain
|
|
7
|
+
Project-URL: Repository, https://github.com/jordan-gibbs/hyperresearch-answers
|
|
8
|
+
Project-URL: Source, https://github.com/jordan-gibbs/hyperresearch-answers/tree/main/packages/langchain-python
|
|
9
|
+
Project-URL: Issues, https://github.com/jordan-gibbs/hyperresearch-answers/issues
|
|
10
|
+
Author: Hyperresearch
|
|
11
|
+
License-Expression: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: agents,answers,citations,hyperresearch,langchain,retriever,search,tools,web-search
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
18
|
+
Requires-Python: <4.0,>=3.10
|
|
19
|
+
Requires-Dist: httpx<1.0,>=0.27
|
|
20
|
+
Requires-Dist: langchain-core<2.0.0,>=1.0.0
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
|
|
23
|
+
# langchain-hyperresearch
|
|
24
|
+
|
|
25
|
+
This package contains the LangChain integration for [Hyperresearch Answers](https://hyperresearch.ai/answers): cited, quote-checked answers and ranked raw sources for agents.
|
|
26
|
+
|
|
27
|
+
## Overview
|
|
28
|
+
|
|
29
|
+
### Details
|
|
30
|
+
|
|
31
|
+
| Class | Package | Serializable | JS support |
|
|
32
|
+
| :--- | :--- | :---: | :---: |
|
|
33
|
+
| `HyperresearchAnswerTool` | `langchain-hyperresearch` | ❌ | ✅ (`@hyperresearch/langchain`) |
|
|
34
|
+
| `HyperresearchSearchTool` | `langchain-hyperresearch` | ❌ | ✅ |
|
|
35
|
+
| `HyperresearchRetriever` | `langchain-hyperresearch` | ❌ | ✅ |
|
|
36
|
+
|
|
37
|
+
### Features
|
|
38
|
+
|
|
39
|
+
- **`HyperresearchAnswerTool`** (`hyperresearch_answer`): one factual question in, one short answer out, with the quotes it rests on, each checked word for word against its page. When nothing supports an answer it returns `not_found` instead of a guess. The research runs on the Hyperresearch side: one tool call instead of a loop of searches, and no pages in the agent's context.
|
|
40
|
+
- **`HyperresearchSearchTool`** (`hyperresearch_search`): ranked raw sources from the open web and about 45 structured sources (company filings, statistics agencies, scholarly indexes, books, government records), with word-for-word passages. No summary.
|
|
41
|
+
- **`HyperresearchRetriever`**: `search` as a retriever, one `Document` per ranked source.
|
|
42
|
+
- Sync and async (`invoke` / `ainvoke`). Tools use `response_format="content_and_artifact"`: the model reads a compact JSON string, and `ToolMessage.artifact` holds the full API response.
|
|
43
|
+
|
|
44
|
+
## Setup
|
|
45
|
+
|
|
46
|
+
### Credentials
|
|
47
|
+
|
|
48
|
+
Create an API key with the `answers:ask` scope at <https://console.hyperresearch.ai/#/keys>. Every account gets $5 of free credit, no card needed.
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
import getpass
|
|
52
|
+
import os
|
|
53
|
+
|
|
54
|
+
if "HYPERRESEARCH_API_KEY" not in os.environ:
|
|
55
|
+
os.environ["HYPERRESEARCH_API_KEY"] = getpass.getpass("Enter your Hyperresearch API key: ")
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Installation
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
pip install -U langchain-hyperresearch
|
|
62
|
+
# or
|
|
63
|
+
uv add langchain-hyperresearch
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Instantiation
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
from langchain_hyperresearch import HyperresearchAnswerTool, HyperresearchSearchTool
|
|
70
|
+
|
|
71
|
+
answer = HyperresearchAnswerTool() # the model picks the mode
|
|
72
|
+
cheap = HyperresearchAnswerTool(mode="fast", max_cost_cents=5)
|
|
73
|
+
search = HyperresearchSearchTool(max_results=5)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
| Parameter | Default | |
|
|
77
|
+
|---|---|---|
|
|
78
|
+
| `api_key` | `HYPERRESEARCH_API_KEY` | |
|
|
79
|
+
| `mode` | the model's choice, else `standard` | Fix the mode. Ask: `fast` 5¢ · `standard` 10¢ (20¢ when it digs deeper) · `max` 50¢. Search: `standard` 5¢ · `max` 15¢. |
|
|
80
|
+
| `max_cost_cents` | none | Answer tool. Caps every call; a standard ask under 20 never escalates. |
|
|
81
|
+
| `max_results` | the model's choice, else 10 | Search tool and retriever. 1-25. |
|
|
82
|
+
| `client` | new client | Share one `HyperresearchClient` (it also takes `base_url`, timeouts, `max_retries`). |
|
|
83
|
+
|
|
84
|
+
## Invocation
|
|
85
|
+
|
|
86
|
+
### Directly
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
answer.invoke({"question": "How old must a US senator be?", "mode": "fast"})
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
```json
|
|
93
|
+
{"id": "ans_01J...", "status": "answered", "answer": "At least 30 years old (US Constitution, Article I, Section 3).", "evidence": [{"url": "https://www.archives.gov/founding-docs/constitution-transcript", "title": "The Constitution of the United States: A Transcription", "quote": "No Person shall be a Senator who shall not have attained to the Age of thirty Years", "check": "verified"}], "price_cents": 5}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
`status` is one of `answered`, `false_premise`, `unconfirmed`, `not_found` or `error`.
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
search.invoke({"query": "minimum age to serve as a US senator"})
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### As a ToolCall
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
model_generated_tool_call = {
|
|
106
|
+
"args": {"question": "How old must a US senator be?"},
|
|
107
|
+
"id": "1",
|
|
108
|
+
"name": answer.name,
|
|
109
|
+
"type": "tool_call",
|
|
110
|
+
}
|
|
111
|
+
msg = answer.invoke(model_generated_tool_call)
|
|
112
|
+
msg.content # the compact JSON the model reads
|
|
113
|
+
msg.artifact # the full API response, including balance_cents
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Within an agent
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
from langchain.agents import create_agent
|
|
120
|
+
|
|
121
|
+
agent = create_agent(
|
|
122
|
+
model="claude-sonnet-4-6",
|
|
123
|
+
tools=[HyperresearchAnswerTool(), HyperresearchSearchTool()],
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
agent.invoke(
|
|
127
|
+
{"messages": [{"role": "user", "content": "What was the US federal deficit in fiscal 2025, with a source?"}]}
|
|
128
|
+
)
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Retriever
|
|
132
|
+
|
|
133
|
+
```python
|
|
134
|
+
from langchain_hyperresearch import HyperresearchRetriever
|
|
135
|
+
|
|
136
|
+
retriever = HyperresearchRetriever(max_results=5)
|
|
137
|
+
docs = retriever.invoke("minimum age to serve as a US senator")
|
|
138
|
+
docs[0].page_content # the matched passages, verbatim
|
|
139
|
+
docs[0].metadata # url, title, rank, source, published, verified, call_id
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Each retrieval is one billed `search` call.
|
|
143
|
+
|
|
144
|
+
## Pricing
|
|
145
|
+
|
|
146
|
+
| Call | Price | If not found |
|
|
147
|
+
|---|---|---|
|
|
148
|
+
| ask · fast | 5¢ | 1¢–5¢ |
|
|
149
|
+
| ask · standard (default) | 10¢, 20¢ when it digs deeper | 2¢–20¢ |
|
|
150
|
+
| ask · max | 50¢ | 10¢–50¢ |
|
|
151
|
+
| search · standard (default) | 5¢ | 0¢–5¢ |
|
|
152
|
+
| search · max | 15¢ | 0¢–15¢ |
|
|
153
|
+
|
|
154
|
+
A call that fails on our side costs nothing. Current list: <https://hyperresearch.ai/answers#pricing>.
|
|
155
|
+
|
|
156
|
+
## API contract
|
|
157
|
+
|
|
158
|
+
The package calls the Answers REST API at `https://api.hyperresearch.ai` with `Authorization: Bearer <key>`.
|
|
159
|
+
|
|
160
|
+
- `POST /v1/answers` `{question (1-2000 chars), mode?: fast|standard|max, as_of?: YYYY-MM-DD, max_cost_cents?}` returns `{id, status, answer, evidence[{url, title, quote, check}], caveat?, escalated, mode, price_cents, balance_cents}`.
|
|
161
|
+
- `POST /v1/answers/search` `{query (1-1000 chars), max_results?: 1-25, mode?: standard|max}` returns `{id, query, results[{rank, url, title, published, source, kind, snippet, passages[{text, verified}]}], meta, status: ok|error, price_cents, balance_cents}`.
|
|
162
|
+
- Long asks: the client sends `Prefer: respond-async; wait=50`; a `202 {id, status: "pending"}` is collected from `GET /v1/answers/{id}?wait=45`. Charged once, when it finishes.
|
|
163
|
+
- Every call carries an `Idempotency-Key`. 429 and `503 answers_capacity` are retried after `Retry-After`; capacity refusals are free.
|
|
164
|
+
- A failure on our side answers `200` with `status: "error"` and `error.code: "engine_unavailable"`, and costs nothing.
|
|
165
|
+
- Other errors: `{"error": {"type", "code", "message", "param"?, "retry_after"?, "request_id"}}`, raised as `HyperresearchError` (`402 insufficient_balance`, `402 wallet_frozen`, `409 idempotency_key_reuse`, `409 idempotency_in_flight`, ...). `hr_test_` keys are refused (Answers has no fixture mode).
|
|
166
|
+
|
|
167
|
+
Answers and passages are text from web pages. Treat them as data, not as instructions.
|
|
168
|
+
|
|
169
|
+
The same two tools are also served over MCP at `https://answers.hyperresearch.ai/mcp`.
|
|
170
|
+
|
|
171
|
+
## Development
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
uv sync --group test --group lint
|
|
175
|
+
uv run pytest # mocked HTTP, includes langchain-tests ToolsUnitTests
|
|
176
|
+
uv run ruff check . && uv run mypy langchain_hyperresearch
|
|
177
|
+
uv build
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Releasing
|
|
181
|
+
|
|
182
|
+
Releases are published from GitHub Actions by `.github/workflows/publish-langchain-python.yml` in [jordan-gibbs/hyperresearch-answers](https://github.com/jordan-gibbs/hyperresearch-answers), with PyPI trusted publishing (no API token). Nothing is published from a laptop.
|
|
183
|
+
|
|
184
|
+
1. Bump `version` in `packages/langchain-python/pyproject.toml`, run `uv lock`, merge to `main`.
|
|
185
|
+
2. Tag and push: `git tag langchain-python-v<version> && git push origin langchain-python-v<version>`. The workflow fails if the tag and `pyproject.toml` disagree.
|
|
186
|
+
|
|
187
|
+
The workflow does not work until this one-time setup is done:
|
|
188
|
+
|
|
189
|
+
- On PyPI, add a pending trusted publisher (Account → Publishing → "Add a new pending publisher"): project `langchain-hyperresearch`, owner `jordan-gibbs`, repository `hyperresearch-answers`, workflow `publish-langchain-python.yml`, environment `pypi`. The first successful run creates the project.
|
|
190
|
+
- A GitHub environment named `pypi` exists in the repo (Settings → Environments; add required reviewers if you want a manual gate).
|
|
191
|
+
|
|
192
|
+
## License
|
|
193
|
+
|
|
194
|
+
MIT
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# langchain-hyperresearch
|
|
2
|
+
|
|
3
|
+
This package contains the LangChain integration for [Hyperresearch Answers](https://hyperresearch.ai/answers): cited, quote-checked answers and ranked raw sources for agents.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
### Details
|
|
8
|
+
|
|
9
|
+
| Class | Package | Serializable | JS support |
|
|
10
|
+
| :--- | :--- | :---: | :---: |
|
|
11
|
+
| `HyperresearchAnswerTool` | `langchain-hyperresearch` | ❌ | ✅ (`@hyperresearch/langchain`) |
|
|
12
|
+
| `HyperresearchSearchTool` | `langchain-hyperresearch` | ❌ | ✅ |
|
|
13
|
+
| `HyperresearchRetriever` | `langchain-hyperresearch` | ❌ | ✅ |
|
|
14
|
+
|
|
15
|
+
### Features
|
|
16
|
+
|
|
17
|
+
- **`HyperresearchAnswerTool`** (`hyperresearch_answer`): one factual question in, one short answer out, with the quotes it rests on, each checked word for word against its page. When nothing supports an answer it returns `not_found` instead of a guess. The research runs on the Hyperresearch side: one tool call instead of a loop of searches, and no pages in the agent's context.
|
|
18
|
+
- **`HyperresearchSearchTool`** (`hyperresearch_search`): ranked raw sources from the open web and about 45 structured sources (company filings, statistics agencies, scholarly indexes, books, government records), with word-for-word passages. No summary.
|
|
19
|
+
- **`HyperresearchRetriever`**: `search` as a retriever, one `Document` per ranked source.
|
|
20
|
+
- Sync and async (`invoke` / `ainvoke`). Tools use `response_format="content_and_artifact"`: the model reads a compact JSON string, and `ToolMessage.artifact` holds the full API response.
|
|
21
|
+
|
|
22
|
+
## Setup
|
|
23
|
+
|
|
24
|
+
### Credentials
|
|
25
|
+
|
|
26
|
+
Create an API key with the `answers:ask` scope at <https://console.hyperresearch.ai/#/keys>. Every account gets $5 of free credit, no card needed.
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
import getpass
|
|
30
|
+
import os
|
|
31
|
+
|
|
32
|
+
if "HYPERRESEARCH_API_KEY" not in os.environ:
|
|
33
|
+
os.environ["HYPERRESEARCH_API_KEY"] = getpass.getpass("Enter your Hyperresearch API key: ")
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Installation
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pip install -U langchain-hyperresearch
|
|
40
|
+
# or
|
|
41
|
+
uv add langchain-hyperresearch
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Instantiation
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
from langchain_hyperresearch import HyperresearchAnswerTool, HyperresearchSearchTool
|
|
48
|
+
|
|
49
|
+
answer = HyperresearchAnswerTool() # the model picks the mode
|
|
50
|
+
cheap = HyperresearchAnswerTool(mode="fast", max_cost_cents=5)
|
|
51
|
+
search = HyperresearchSearchTool(max_results=5)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
| Parameter | Default | |
|
|
55
|
+
|---|---|---|
|
|
56
|
+
| `api_key` | `HYPERRESEARCH_API_KEY` | |
|
|
57
|
+
| `mode` | the model's choice, else `standard` | Fix the mode. Ask: `fast` 5¢ · `standard` 10¢ (20¢ when it digs deeper) · `max` 50¢. Search: `standard` 5¢ · `max` 15¢. |
|
|
58
|
+
| `max_cost_cents` | none | Answer tool. Caps every call; a standard ask under 20 never escalates. |
|
|
59
|
+
| `max_results` | the model's choice, else 10 | Search tool and retriever. 1-25. |
|
|
60
|
+
| `client` | new client | Share one `HyperresearchClient` (it also takes `base_url`, timeouts, `max_retries`). |
|
|
61
|
+
|
|
62
|
+
## Invocation
|
|
63
|
+
|
|
64
|
+
### Directly
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
answer.invoke({"question": "How old must a US senator be?", "mode": "fast"})
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{"id": "ans_01J...", "status": "answered", "answer": "At least 30 years old (US Constitution, Article I, Section 3).", "evidence": [{"url": "https://www.archives.gov/founding-docs/constitution-transcript", "title": "The Constitution of the United States: A Transcription", "quote": "No Person shall be a Senator who shall not have attained to the Age of thirty Years", "check": "verified"}], "price_cents": 5}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
`status` is one of `answered`, `false_premise`, `unconfirmed`, `not_found` or `error`.
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
search.invoke({"query": "minimum age to serve as a US senator"})
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### As a ToolCall
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
model_generated_tool_call = {
|
|
84
|
+
"args": {"question": "How old must a US senator be?"},
|
|
85
|
+
"id": "1",
|
|
86
|
+
"name": answer.name,
|
|
87
|
+
"type": "tool_call",
|
|
88
|
+
}
|
|
89
|
+
msg = answer.invoke(model_generated_tool_call)
|
|
90
|
+
msg.content # the compact JSON the model reads
|
|
91
|
+
msg.artifact # the full API response, including balance_cents
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Within an agent
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from langchain.agents import create_agent
|
|
98
|
+
|
|
99
|
+
agent = create_agent(
|
|
100
|
+
model="claude-sonnet-4-6",
|
|
101
|
+
tools=[HyperresearchAnswerTool(), HyperresearchSearchTool()],
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
agent.invoke(
|
|
105
|
+
{"messages": [{"role": "user", "content": "What was the US federal deficit in fiscal 2025, with a source?"}]}
|
|
106
|
+
)
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Retriever
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
from langchain_hyperresearch import HyperresearchRetriever
|
|
113
|
+
|
|
114
|
+
retriever = HyperresearchRetriever(max_results=5)
|
|
115
|
+
docs = retriever.invoke("minimum age to serve as a US senator")
|
|
116
|
+
docs[0].page_content # the matched passages, verbatim
|
|
117
|
+
docs[0].metadata # url, title, rank, source, published, verified, call_id
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Each retrieval is one billed `search` call.
|
|
121
|
+
|
|
122
|
+
## Pricing
|
|
123
|
+
|
|
124
|
+
| Call | Price | If not found |
|
|
125
|
+
|---|---|---|
|
|
126
|
+
| ask · fast | 5¢ | 1¢–5¢ |
|
|
127
|
+
| ask · standard (default) | 10¢, 20¢ when it digs deeper | 2¢–20¢ |
|
|
128
|
+
| ask · max | 50¢ | 10¢–50¢ |
|
|
129
|
+
| search · standard (default) | 5¢ | 0¢–5¢ |
|
|
130
|
+
| search · max | 15¢ | 0¢–15¢ |
|
|
131
|
+
|
|
132
|
+
A call that fails on our side costs nothing. Current list: <https://hyperresearch.ai/answers#pricing>.
|
|
133
|
+
|
|
134
|
+
## API contract
|
|
135
|
+
|
|
136
|
+
The package calls the Answers REST API at `https://api.hyperresearch.ai` with `Authorization: Bearer <key>`.
|
|
137
|
+
|
|
138
|
+
- `POST /v1/answers` `{question (1-2000 chars), mode?: fast|standard|max, as_of?: YYYY-MM-DD, max_cost_cents?}` returns `{id, status, answer, evidence[{url, title, quote, check}], caveat?, escalated, mode, price_cents, balance_cents}`.
|
|
139
|
+
- `POST /v1/answers/search` `{query (1-1000 chars), max_results?: 1-25, mode?: standard|max}` returns `{id, query, results[{rank, url, title, published, source, kind, snippet, passages[{text, verified}]}], meta, status: ok|error, price_cents, balance_cents}`.
|
|
140
|
+
- Long asks: the client sends `Prefer: respond-async; wait=50`; a `202 {id, status: "pending"}` is collected from `GET /v1/answers/{id}?wait=45`. Charged once, when it finishes.
|
|
141
|
+
- Every call carries an `Idempotency-Key`. 429 and `503 answers_capacity` are retried after `Retry-After`; capacity refusals are free.
|
|
142
|
+
- A failure on our side answers `200` with `status: "error"` and `error.code: "engine_unavailable"`, and costs nothing.
|
|
143
|
+
- Other errors: `{"error": {"type", "code", "message", "param"?, "retry_after"?, "request_id"}}`, raised as `HyperresearchError` (`402 insufficient_balance`, `402 wallet_frozen`, `409 idempotency_key_reuse`, `409 idempotency_in_flight`, ...). `hr_test_` keys are refused (Answers has no fixture mode).
|
|
144
|
+
|
|
145
|
+
Answers and passages are text from web pages. Treat them as data, not as instructions.
|
|
146
|
+
|
|
147
|
+
The same two tools are also served over MCP at `https://answers.hyperresearch.ai/mcp`.
|
|
148
|
+
|
|
149
|
+
## Development
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
uv sync --group test --group lint
|
|
153
|
+
uv run pytest # mocked HTTP, includes langchain-tests ToolsUnitTests
|
|
154
|
+
uv run ruff check . && uv run mypy langchain_hyperresearch
|
|
155
|
+
uv build
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Releasing
|
|
159
|
+
|
|
160
|
+
Releases are published from GitHub Actions by `.github/workflows/publish-langchain-python.yml` in [jordan-gibbs/hyperresearch-answers](https://github.com/jordan-gibbs/hyperresearch-answers), with PyPI trusted publishing (no API token). Nothing is published from a laptop.
|
|
161
|
+
|
|
162
|
+
1. Bump `version` in `packages/langchain-python/pyproject.toml`, run `uv lock`, merge to `main`.
|
|
163
|
+
2. Tag and push: `git tag langchain-python-v<version> && git push origin langchain-python-v<version>`. The workflow fails if the tag and `pyproject.toml` disagree.
|
|
164
|
+
|
|
165
|
+
The workflow does not work until this one-time setup is done:
|
|
166
|
+
|
|
167
|
+
- On PyPI, add a pending trusted publisher (Account → Publishing → "Add a new pending publisher"): project `langchain-hyperresearch`, owner `jordan-gibbs`, repository `hyperresearch-answers`, workflow `publish-langchain-python.yml`, environment `pypi`. The first successful run creates the project.
|
|
168
|
+
- A GitHub environment named `pypi` exists in the repo (Settings → Environments; add required reviewers if you want a manual gate).
|
|
169
|
+
|
|
170
|
+
## License
|
|
171
|
+
|
|
172
|
+
MIT
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""LangChain integration for Hyperresearch Answers."""
|
|
2
|
+
|
|
3
|
+
from langchain_hyperresearch._client import (
|
|
4
|
+
DEFAULT_BASE_URL,
|
|
5
|
+
HyperresearchClient,
|
|
6
|
+
HyperresearchError,
|
|
7
|
+
__version__,
|
|
8
|
+
)
|
|
9
|
+
from langchain_hyperresearch.retrievers import HyperresearchRetriever
|
|
10
|
+
from langchain_hyperresearch.tools import (
|
|
11
|
+
HyperresearchAnswerInput,
|
|
12
|
+
HyperresearchAnswerTool,
|
|
13
|
+
HyperresearchSearchInput,
|
|
14
|
+
HyperresearchSearchTool,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"DEFAULT_BASE_URL",
|
|
19
|
+
"HyperresearchAnswerInput",
|
|
20
|
+
"HyperresearchAnswerTool",
|
|
21
|
+
"HyperresearchClient",
|
|
22
|
+
"HyperresearchError",
|
|
23
|
+
"HyperresearchRetriever",
|
|
24
|
+
"HyperresearchSearchInput",
|
|
25
|
+
"HyperresearchSearchTool",
|
|
26
|
+
"__version__",
|
|
27
|
+
]
|