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.
@@ -0,0 +1,5 @@
1
+ __pycache__/
2
+ *.pyc
3
+ dist/
4
+ node_modules/
5
+ .env
@@ -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})