langchain-callin 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_callin-0.1.0/.gitignore +5 -0
- langchain_callin-0.1.0/LICENSE +21 -0
- langchain_callin-0.1.0/PKG-INFO +50 -0
- langchain_callin-0.1.0/README.md +31 -0
- langchain_callin-0.1.0/pyproject.toml +23 -0
- langchain_callin-0.1.0/src/langchain_callin/__init__.py +83 -0
- langchain_callin-0.1.0/tests/test_tools.py +16 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Replacing Humans LLC (Callin.io)
|
|
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,50 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: langchain-callin
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: LangChain integration for Callin.io: let your agent place real phone calls with an AI voice agent and read the summary and transcript.
|
|
5
|
+
Project-URL: Homepage, https://callin.io
|
|
6
|
+
Project-URL: Documentation, https://github.com/callin-io/callin-agents/tree/main/python-langchain
|
|
7
|
+
Project-URL: Source, https://github.com/callin-io/callin-agents
|
|
8
|
+
Author-email: "Callin.io" <hello@callin.io>
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: ai agents,callin,langchain,phone calls,telephony,voice ai
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Topic :: Communications :: Telephony
|
|
15
|
+
Requires-Python: >=3.9
|
|
16
|
+
Requires-Dist: callin>=0.1.0
|
|
17
|
+
Requires-Dist: langchain-core>=0.2
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# langchain-callin
|
|
21
|
+
|
|
22
|
+
LangChain integration for [Callin.io](https://callin.io): give your agent a real phone line.
|
|
23
|
+
The agent places a call with an AI voice agent that pursues an objective (book a table,
|
|
24
|
+
confirm an appointment, ask a supplier for a quote), then reads the summary and transcript.
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install langchain-callin
|
|
28
|
+
export CALLIN_API_KEY=... # app.callin.io > Settings > API
|
|
29
|
+
export CALLIN_AGENT_ID=... # the outbound voice agent that makes the calls
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
from langchain_callin import CallinToolkit
|
|
34
|
+
|
|
35
|
+
tools = CallinToolkit().get_tools()
|
|
36
|
+
# callin_place_call, callin_get_call_result, callin_list_recent_calls
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Or a single tool:
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
from langchain_callin import CallinPlaceCall
|
|
43
|
+
CallinPlaceCall().invoke({"to": "+390111234567", "objective": "Book a table for 2 tomorrow at 20:30 under the name Rossi", "language": "it"})
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Calls are asynchronous: `callin_place_call` returns a `campaign_id`, then `callin_get_call_result`
|
|
47
|
+
returns status, summary and transcript once the call ends. The voice agent always tells the
|
|
48
|
+
person it is an AI assistant. Use it only for calls the person would expect (no cold calling).
|
|
49
|
+
|
|
50
|
+
Built on the [`callin`](https://pypi.org/project/callin/) Python SDK. MIT license.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# langchain-callin
|
|
2
|
+
|
|
3
|
+
LangChain integration for [Callin.io](https://callin.io): give your agent a real phone line.
|
|
4
|
+
The agent places a call with an AI voice agent that pursues an objective (book a table,
|
|
5
|
+
confirm an appointment, ask a supplier for a quote), then reads the summary and transcript.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install langchain-callin
|
|
9
|
+
export CALLIN_API_KEY=... # app.callin.io > Settings > API
|
|
10
|
+
export CALLIN_AGENT_ID=... # the outbound voice agent that makes the calls
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from langchain_callin import CallinToolkit
|
|
15
|
+
|
|
16
|
+
tools = CallinToolkit().get_tools()
|
|
17
|
+
# callin_place_call, callin_get_call_result, callin_list_recent_calls
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Or a single tool:
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
from langchain_callin import CallinPlaceCall
|
|
24
|
+
CallinPlaceCall().invoke({"to": "+390111234567", "objective": "Book a table for 2 tomorrow at 20:30 under the name Rossi", "language": "it"})
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Calls are asynchronous: `callin_place_call` returns a `campaign_id`, then `callin_get_call_result`
|
|
28
|
+
returns status, summary and transcript once the call ends. The voice agent always tells the
|
|
29
|
+
person it is an AI assistant. Use it only for calls the person would expect (no cold calling).
|
|
30
|
+
|
|
31
|
+
Built on the [`callin`](https://pypi.org/project/callin/) Python SDK. MIT license.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "langchain-callin"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "LangChain integration for Callin.io: let your agent place real phone calls with an AI voice agent and read the summary and transcript."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "Callin.io", email = "hello@callin.io" }]
|
|
13
|
+
keywords = ["langchain", "ai agents", "phone calls", "voice ai", "telephony", "callin"]
|
|
14
|
+
dependencies = ["callin>=0.1.0", "langchain-core>=0.2"]
|
|
15
|
+
classifiers = ["Programming Language :: Python :: 3", "License :: OSI Approved :: MIT License", "Topic :: Communications :: Telephony"]
|
|
16
|
+
|
|
17
|
+
[project.urls]
|
|
18
|
+
Homepage = "https://callin.io"
|
|
19
|
+
Documentation = "https://github.com/callin-io/callin-agents/tree/main/python-langchain"
|
|
20
|
+
Source = "https://github.com/callin-io/callin-agents"
|
|
21
|
+
|
|
22
|
+
[tool.hatch.build.targets.wheel]
|
|
23
|
+
packages = ["src/langchain_callin"]
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""LangChain integration for Callin.io phone calls."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import json
|
|
5
|
+
from typing import Any, List, Optional, Type
|
|
6
|
+
|
|
7
|
+
from callin import Callin
|
|
8
|
+
from langchain_core.tools import BaseTool, BaseToolkit
|
|
9
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
10
|
+
|
|
11
|
+
__all__ = ["CallinPlaceCall", "CallinGetCallResult", "CallinListRecentCalls", "CallinToolkit"]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class _PlaceCallInput(BaseModel):
|
|
15
|
+
to: str = Field(description="Phone number in E.164 format, e.g. +390111234567.")
|
|
16
|
+
objective: str = Field(description="What the call must achieve, e.g. 'Book a table for 2 tomorrow at 20:30 under the name Rossi'.")
|
|
17
|
+
context: str = Field(default="", description="Facts the caller may share: names, order numbers, callback number.")
|
|
18
|
+
language: str = Field(default="", description="Language code for the call, e.g. 'it', 'es', 'pt', 'en'.")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class _CampaignInput(BaseModel):
|
|
22
|
+
campaign_id: str = Field(description="The campaign_id returned by callin_place_call.")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class _ListInput(BaseModel):
|
|
26
|
+
limit: int = Field(default=10, description="How many recent calls to return.")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class _CallinTool(BaseTool):
|
|
30
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
31
|
+
client: Optional[Any] = None # a callin.Callin instance
|
|
32
|
+
|
|
33
|
+
def _c(self) -> Callin:
|
|
34
|
+
if self.client is None:
|
|
35
|
+
self.client = Callin() # reads CALLIN_API_KEY and CALLIN_AGENT_ID
|
|
36
|
+
return self.client
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class CallinPlaceCall(_CallinTool):
|
|
40
|
+
"""Place a real outbound phone call with a Callin.io AI voice agent."""
|
|
41
|
+
|
|
42
|
+
name: str = "callin_place_call"
|
|
43
|
+
description: str = (
|
|
44
|
+
"Place a real phone call with an AI voice agent that pursues an objective "
|
|
45
|
+
"(book, confirm, ask, remind). Asynchronous: returns JSON with campaign_id; "
|
|
46
|
+
"then use callin_get_call_result. The voice agent always discloses it is an AI."
|
|
47
|
+
)
|
|
48
|
+
args_schema: Type[BaseModel] = _PlaceCallInput
|
|
49
|
+
|
|
50
|
+
def _run(self, to: str, objective: str, context: str = "", language: str = "", run_manager=None) -> str:
|
|
51
|
+
return json.dumps(self._c().place_call(to=to, objective=objective, context=context, language=language).to_dict())
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class CallinGetCallResult(_CallinTool):
|
|
55
|
+
"""Read status, summary and transcript of a call placed with CallinPlaceCall."""
|
|
56
|
+
|
|
57
|
+
name: str = "callin_get_call_result"
|
|
58
|
+
description: str = "Get the status of a call placed with callin_place_call and, once finished, its summary and transcript (JSON)."
|
|
59
|
+
args_schema: Type[BaseModel] = _CampaignInput
|
|
60
|
+
|
|
61
|
+
def _run(self, campaign_id: str, run_manager=None) -> str:
|
|
62
|
+
return json.dumps(self._c().get_call_result(campaign_id).to_dict())
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class CallinListRecentCalls(_CallinTool):
|
|
66
|
+
"""List recent calls handled by your Callin.io voice agents."""
|
|
67
|
+
|
|
68
|
+
name: str = "callin_list_recent_calls"
|
|
69
|
+
description: str = "List recent calls handled by your Callin.io voice agents, with summaries (JSON)."
|
|
70
|
+
args_schema: Type[BaseModel] = _ListInput
|
|
71
|
+
|
|
72
|
+
def _run(self, limit: int = 10, run_manager=None) -> str:
|
|
73
|
+
return json.dumps(self._c().list_conversations(page_size=limit))
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class CallinToolkit(BaseToolkit):
|
|
77
|
+
"""All Callin.io tools in one toolkit."""
|
|
78
|
+
|
|
79
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
80
|
+
client: Optional[Any] = None # a callin.Callin instance
|
|
81
|
+
|
|
82
|
+
def get_tools(self) -> List[BaseTool]:
|
|
83
|
+
return [CallinPlaceCall(client=self.client), CallinGetCallResult(client=self.client), CallinListRecentCalls(client=self.client)]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from langchain_callin import CallinToolkit
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Fake:
|
|
5
|
+
def list_conversations(self, page_size=10):
|
|
6
|
+
return {"items": [], "page_size": page_size}
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def test_toolkit_names():
|
|
10
|
+
names = [t.name for t in CallinToolkit(client=Fake()).get_tools()]
|
|
11
|
+
assert names == ["callin_place_call", "callin_get_call_result", "callin_list_recent_calls"]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def test_list_runs():
|
|
15
|
+
tool = CallinToolkit(client=Fake()).get_tools()[2]
|
|
16
|
+
assert '"page_size": 3' in tool.invoke({"limit": 3})
|