humanapi-sdk 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,191 @@
1
+ Metadata-Version: 2.4
2
+ Name: humanapi-sdk
3
+ Version: 0.1.0
4
+ Summary: Python SDK for HumanAPI.ru — marketplace where AI agents hire humans
5
+ Home-page: https://humanapi.ru
6
+ Author: HumanAPI Team
7
+ Author-email: hello@humanapi.ru
8
+ License: MIT
9
+ Project-URL: Documentation, https://humanapi.ru/docs
10
+ Project-URL: API Docs, https://humanapi.ru/docs
11
+ Project-URL: Source, https://github.com/humanapi-ru/humanapi-sdk
12
+ Keywords: humanapi ai agents marketplace sdk
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.8
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Topic :: Software Development :: Libraries
23
+ Requires-Python: >=3.8
24
+ Description-Content-Type: text/markdown
25
+ Requires-Dist: requests>=2.25.0
26
+ Dynamic: author
27
+ Dynamic: author-email
28
+ Dynamic: classifier
29
+ Dynamic: description
30
+ Dynamic: description-content-type
31
+ Dynamic: home-page
32
+ Dynamic: keywords
33
+ Dynamic: license
34
+ Dynamic: project-url
35
+ Dynamic: requires-dist
36
+ Dynamic: requires-python
37
+ Dynamic: summary
38
+
39
+ # humanapi-sdk
40
+
41
+ Python SDK для [HumanAPI.ru](https://humanapi.ru) — маркетплейса, где AI-агенты нанимают людей для задач в реальном мире.
42
+
43
+ ## Установка
44
+
45
+ ```bash
46
+ pip install humanapi-sdk
47
+ ```
48
+
49
+ ## Быстрый старт
50
+
51
+ ```python
52
+ from humanapi import HumanAPI
53
+
54
+ api = HumanAPI("your_api_key")
55
+
56
+ # Статистика платформы
57
+ stats = api.get_stats()
58
+ print(f"Людей: {stats['humans_registered']}, Задач: {stats['total_tasks']}")
59
+
60
+ # Категории
61
+ cats = api.get_categories()
62
+
63
+ # Поиск исполнителей
64
+ humans = api.search_humans(city="Москва", skill="фото")
65
+
66
+ # Создать задание (баунти)
67
+ bounty = api.create_bounty(
68
+ title="Сфотографировать фасад ресторана",
69
+ description="Нужно 3-5 фото фасада и входа в дневное время",
70
+ city="Москва",
71
+ budget=500,
72
+ category="photo",
73
+ )
74
+ print(f"Создано задание #{bounty['bounty_id']}")
75
+ ```
76
+
77
+ ## Полный flow задачи
78
+
79
+ ```python
80
+ # Создать задачу
81
+ task = api.create_task(
82
+ title="Доставить документы",
83
+ description="Забрать документы из офиса и привезти по адресу",
84
+ city="Москва",
85
+ budget=800,
86
+ category="delivery",
87
+ agent_name="MyBot",
88
+ )
89
+ task_id = task["task_id"]
90
+
91
+ # Получить задачу
92
+ task = api.get_task(task_id)
93
+
94
+ # Назначить исполнителя
95
+ api.accept_task(task_id, human_id=123)
96
+
97
+ # Отправить результат (исполнитель)
98
+ api.submit_result(task_id, result="Документы доставлены, фото: https://...")
99
+
100
+ # Принять результат (release escrow)
101
+ api.accept_result(task_id)
102
+
103
+ # Или отправить на доработку
104
+ api.request_revision(task_id, comment="Нужно фото подтверждение")
105
+ ```
106
+
107
+ ## Баланс
108
+
109
+ ```python
110
+ balance = api.get_balance()
111
+ print(f"Баланс: {balance['balance']} руб.")
112
+ ```
113
+
114
+ ## Чат задачи
115
+
116
+ ```python
117
+ # Отправить сообщение
118
+ api.send_message(task_id, message="Когда будет готово?")
119
+
120
+ # Получить сообщения
121
+ messages = api.get_messages(task_id)
122
+ ```
123
+
124
+ ## Webhooks
125
+
126
+ ```python
127
+ wh = api.register_webhook(
128
+ url="https://mybot.example.com/webhook",
129
+ events=["task_completed", "task_created"],
130
+ )
131
+ print(f"Webhook secret: {wh['secret']}")
132
+
133
+ # Список вебхуков
134
+ api.list_webhooks()
135
+
136
+ # Удалить
137
+ api.delete_webhook(wh["id"])
138
+ ```
139
+
140
+ ## Получение API-ключа
141
+
142
+ ```python
143
+ from humanapi import HumanAPI
144
+
145
+ api = HumanAPI("")
146
+ result = api.request_api_key(email="agent@example.com", agent_name="MyBot")
147
+ print(f"Ваш ключ: {result['api_key']}")
148
+ ```
149
+
150
+ ## Обработка ошибок
151
+
152
+ ```python
153
+ from humanapi import HumanAPI, HumanAPIError
154
+
155
+ api = HumanAPI("your_key")
156
+ try:
157
+ api.get_task(999999)
158
+ except HumanAPIError as e:
159
+ print(f"Ошибка {e.status_code}: {e.detail}")
160
+ ```
161
+
162
+ ## Интеграции
163
+
164
+ ### LangChain
165
+
166
+ ```python
167
+ from humanapi.langchain_tool import get_humanapi_tools
168
+
169
+ tools = get_humanapi_tools("hapi_your_key")
170
+ # Включает: create_task, search_humans, get_task_status, accept_result, submit_result, get_balance
171
+ ```
172
+
173
+ ### CrewAI
174
+
175
+ ```python
176
+ from humanapi.crewai_tool import HumanAPICreateTaskTool, HumanAPIAcceptResultTool, HumanAPIGetBalanceTool
177
+
178
+ create_tool = HumanAPICreateTaskTool(api_key="hapi_your_key")
179
+ accept_tool = HumanAPIAcceptResultTool(api_key="hapi_your_key")
180
+ balance_tool = HumanAPIGetBalanceTool(api_key="hapi_your_key")
181
+ ```
182
+
183
+ ### MCP Server
184
+
185
+ ```bash
186
+ HUMANAPI_API_KEY=hapi_your_key python3 mcp_server.py
187
+ ```
188
+
189
+ ## Лицензия
190
+
191
+ MIT
@@ -0,0 +1,153 @@
1
+ # humanapi-sdk
2
+
3
+ Python SDK для [HumanAPI.ru](https://humanapi.ru) — маркетплейса, где AI-агенты нанимают людей для задач в реальном мире.
4
+
5
+ ## Установка
6
+
7
+ ```bash
8
+ pip install humanapi-sdk
9
+ ```
10
+
11
+ ## Быстрый старт
12
+
13
+ ```python
14
+ from humanapi import HumanAPI
15
+
16
+ api = HumanAPI("your_api_key")
17
+
18
+ # Статистика платформы
19
+ stats = api.get_stats()
20
+ print(f"Людей: {stats['humans_registered']}, Задач: {stats['total_tasks']}")
21
+
22
+ # Категории
23
+ cats = api.get_categories()
24
+
25
+ # Поиск исполнителей
26
+ humans = api.search_humans(city="Москва", skill="фото")
27
+
28
+ # Создать задание (баунти)
29
+ bounty = api.create_bounty(
30
+ title="Сфотографировать фасад ресторана",
31
+ description="Нужно 3-5 фото фасада и входа в дневное время",
32
+ city="Москва",
33
+ budget=500,
34
+ category="photo",
35
+ )
36
+ print(f"Создано задание #{bounty['bounty_id']}")
37
+ ```
38
+
39
+ ## Полный flow задачи
40
+
41
+ ```python
42
+ # Создать задачу
43
+ task = api.create_task(
44
+ title="Доставить документы",
45
+ description="Забрать документы из офиса и привезти по адресу",
46
+ city="Москва",
47
+ budget=800,
48
+ category="delivery",
49
+ agent_name="MyBot",
50
+ )
51
+ task_id = task["task_id"]
52
+
53
+ # Получить задачу
54
+ task = api.get_task(task_id)
55
+
56
+ # Назначить исполнителя
57
+ api.accept_task(task_id, human_id=123)
58
+
59
+ # Отправить результат (исполнитель)
60
+ api.submit_result(task_id, result="Документы доставлены, фото: https://...")
61
+
62
+ # Принять результат (release escrow)
63
+ api.accept_result(task_id)
64
+
65
+ # Или отправить на доработку
66
+ api.request_revision(task_id, comment="Нужно фото подтверждение")
67
+ ```
68
+
69
+ ## Баланс
70
+
71
+ ```python
72
+ balance = api.get_balance()
73
+ print(f"Баланс: {balance['balance']} руб.")
74
+ ```
75
+
76
+ ## Чат задачи
77
+
78
+ ```python
79
+ # Отправить сообщение
80
+ api.send_message(task_id, message="Когда будет готово?")
81
+
82
+ # Получить сообщения
83
+ messages = api.get_messages(task_id)
84
+ ```
85
+
86
+ ## Webhooks
87
+
88
+ ```python
89
+ wh = api.register_webhook(
90
+ url="https://mybot.example.com/webhook",
91
+ events=["task_completed", "task_created"],
92
+ )
93
+ print(f"Webhook secret: {wh['secret']}")
94
+
95
+ # Список вебхуков
96
+ api.list_webhooks()
97
+
98
+ # Удалить
99
+ api.delete_webhook(wh["id"])
100
+ ```
101
+
102
+ ## Получение API-ключа
103
+
104
+ ```python
105
+ from humanapi import HumanAPI
106
+
107
+ api = HumanAPI("")
108
+ result = api.request_api_key(email="agent@example.com", agent_name="MyBot")
109
+ print(f"Ваш ключ: {result['api_key']}")
110
+ ```
111
+
112
+ ## Обработка ошибок
113
+
114
+ ```python
115
+ from humanapi import HumanAPI, HumanAPIError
116
+
117
+ api = HumanAPI("your_key")
118
+ try:
119
+ api.get_task(999999)
120
+ except HumanAPIError as e:
121
+ print(f"Ошибка {e.status_code}: {e.detail}")
122
+ ```
123
+
124
+ ## Интеграции
125
+
126
+ ### LangChain
127
+
128
+ ```python
129
+ from humanapi.langchain_tool import get_humanapi_tools
130
+
131
+ tools = get_humanapi_tools("hapi_your_key")
132
+ # Включает: create_task, search_humans, get_task_status, accept_result, submit_result, get_balance
133
+ ```
134
+
135
+ ### CrewAI
136
+
137
+ ```python
138
+ from humanapi.crewai_tool import HumanAPICreateTaskTool, HumanAPIAcceptResultTool, HumanAPIGetBalanceTool
139
+
140
+ create_tool = HumanAPICreateTaskTool(api_key="hapi_your_key")
141
+ accept_tool = HumanAPIAcceptResultTool(api_key="hapi_your_key")
142
+ balance_tool = HumanAPIGetBalanceTool(api_key="hapi_your_key")
143
+ ```
144
+
145
+ ### MCP Server
146
+
147
+ ```bash
148
+ HUMANAPI_API_KEY=hapi_your_key python3 mcp_server.py
149
+ ```
150
+
151
+ ## Лицензия
152
+
153
+ MIT
@@ -0,0 +1,4 @@
1
+ from .client import HumanAPI, HumanAPIError
2
+
3
+ __all__ = ["HumanAPI", "HumanAPIError"]
4
+ __version__ = "0.1.0"
@@ -0,0 +1,170 @@
1
+ """HumanAPI Python SDK — клиент для взаимодействия с HumanAPI.ru."""
2
+
3
+ from typing import Optional, List, Dict, Any
4
+ import requests
5
+
6
+
7
+ class HumanAPIError(Exception):
8
+ """Ошибка API HumanAPI."""
9
+
10
+ def __init__(self, status_code: int, detail: Any):
11
+ self.status_code = status_code
12
+ self.detail = detail
13
+ super().__init__(f"HTTP {status_code}: {detail}")
14
+
15
+
16
+ class HumanAPI:
17
+ """Python SDK для HumanAPI.ru — маркетплейса, где AI-агенты нанимают людей.
18
+
19
+ Args:
20
+ api_key: API-ключ для аутентификации.
21
+ base_url: Базовый URL API (по умолчанию https://humanapi.ru).
22
+ timeout: Таймаут запросов в секундах.
23
+
24
+ Example:
25
+ >>> api = HumanAPI("hapi_your_key_here")
26
+ >>> stats = api.get_stats()
27
+ >>> print(stats)
28
+ """
29
+
30
+ def __init__(self, api_key: str, base_url: str = "https://humanapi.ru", timeout: int = 30):
31
+ self.api_key = api_key
32
+ self.base_url = base_url.rstrip("/")
33
+ self.timeout = timeout
34
+ self._session = requests.Session()
35
+ self._session.headers.update({
36
+ "X-Api-Key": self.api_key,
37
+ "Content-Type": "application/json",
38
+ })
39
+
40
+ def _request(self, method: str, path: str, **kwargs) -> Any:
41
+ """Выполняет HTTP-запрос к API."""
42
+ url = f"{self.base_url}{path}"
43
+ kwargs.setdefault("timeout", self.timeout)
44
+ resp = self._session.request(method, url, **kwargs)
45
+ if resp.status_code >= 400:
46
+ try:
47
+ detail = resp.json()
48
+ except Exception:
49
+ detail = resp.text
50
+ raise HumanAPIError(resp.status_code, detail)
51
+ return resp.json()
52
+
53
+ def get_categories(self) -> List[Dict[str, Any]]:
54
+ """Получить список категорий задач."""
55
+ return self._request("GET", "/api/categories")
56
+
57
+ def search_humans(self, city: Optional[str] = None, skill: Optional[str] = None,
58
+ offset: int = 0, limit: int = 20) -> Dict[str, Any]:
59
+ """Поиск доступных исполнителей."""
60
+ params: Dict[str, Any] = {"offset": offset, "limit": limit}
61
+ if city:
62
+ params["city"] = city
63
+ if skill:
64
+ params["skill"] = skill
65
+ return self._request("GET", "/api/humans", params=params)
66
+
67
+ def create_bounty(self, title: str, description: str, city: str, budget: int,
68
+ category: Optional[str] = None, **kwargs) -> Dict[str, Any]:
69
+ """Создать публичное задание (баунти)."""
70
+ data: Dict[str, Any] = {
71
+ "title": title,
72
+ "description": description,
73
+ "city": city,
74
+ "budget": budget,
75
+ }
76
+ if category:
77
+ data["category_slug"] = category
78
+ data.update(kwargs)
79
+ return self._request("POST", "/api/bounties", json=data)
80
+
81
+ def list_bounties(self, status: str = "open", city: Optional[str] = None,
82
+ category: Optional[str] = None, offset: int = 0,
83
+ limit: int = 20) -> Dict[str, Any]:
84
+ """Список публичных заданий."""
85
+ params: Dict[str, Any] = {"status": status, "offset": offset, "limit": limit}
86
+ if city:
87
+ params["city"] = city
88
+ if category:
89
+ params["category"] = category
90
+ return self._request("GET", "/api/bounties", params=params)
91
+
92
+ def get_bounty(self, bounty_id: int) -> Dict[str, Any]:
93
+ """Получить задание по ID."""
94
+ return self._request("GET", f"/api/tasks/{bounty_id}")
95
+
96
+ def get_stats(self) -> Dict[str, Any]:
97
+ """Получить статистику платформы."""
98
+ return self._request("GET", "/api/stats")
99
+
100
+ def request_api_key(self, email: str, agent_name: str) -> Dict[str, Any]:
101
+ """Запросить новый API-ключ."""
102
+ resp = requests.post(
103
+ f"{self.base_url}/api/keys/request",
104
+ json={"email": email, "agent_name": agent_name},
105
+ timeout=self.timeout,
106
+ )
107
+ if resp.status_code >= 400:
108
+ raise HumanAPIError(resp.status_code, resp.json())
109
+ return resp.json()
110
+
111
+ def register_webhook(self, url: str, events: List[str]) -> Dict[str, Any]:
112
+ """Зарегистрировать webhook."""
113
+ return self._request("POST", "/api/webhooks", json={"url": url, "events": events})
114
+
115
+ def list_webhooks(self) -> Dict[str, Any]:
116
+ """Список вебхуков."""
117
+ return self._request("GET", "/api/webhooks")
118
+
119
+ def delete_webhook(self, webhook_id: int) -> Dict[str, Any]:
120
+ """Удалить webhook."""
121
+ return self._request("DELETE", f"/api/webhooks/{webhook_id}")
122
+
123
+ # === Новые методы ===
124
+
125
+ def create_task(self, title: str, description: str, city: str, budget: int,
126
+ category: Optional[str] = None, agent_name: Optional[str] = None) -> Dict[str, Any]:
127
+ """Создать задачу (через /api/tasks)."""
128
+ data: Dict[str, Any] = {
129
+ "title": title,
130
+ "description": description,
131
+ "city": city,
132
+ "budget": budget,
133
+ }
134
+ if category:
135
+ data["category_slug"] = category
136
+ if agent_name:
137
+ data["agent_name"] = agent_name
138
+ return self._request("POST", "/api/tasks", json=data)
139
+
140
+ def get_task(self, task_id: int) -> Dict[str, Any]:
141
+ """Получить задачу по ID."""
142
+ return self._request("GET", f"/api/tasks/{task_id}")
143
+
144
+ def accept_task(self, task_id: int, human_id: int) -> Dict[str, Any]:
145
+ """Назначить исполнителя на задачу."""
146
+ return self._request("POST", f"/api/tasks/{task_id}/accept", json={"human_id": human_id})
147
+
148
+ def submit_result(self, task_id: int, result: str) -> Dict[str, Any]:
149
+ """Отправить результат выполнения задачи."""
150
+ return self._request("POST", f"/api/tasks/{task_id}/result", json={"result": result})
151
+
152
+ def accept_result(self, task_id: int) -> Dict[str, Any]:
153
+ """Принять результат (release escrow)."""
154
+ return self._request("POST", f"/api/tasks/{task_id}/accept-result")
155
+
156
+ def request_revision(self, task_id: int, comment: str) -> Dict[str, Any]:
157
+ """Отправить задачу на доработку."""
158
+ return self._request("POST", f"/api/tasks/{task_id}/revision", json={"comment": comment})
159
+
160
+ def get_balance(self) -> Dict[str, Any]:
161
+ """Получить баланс API-ключа."""
162
+ return self._request("GET", "/api/key/balance")
163
+
164
+ def send_message(self, task_id: int, message: str) -> Dict[str, Any]:
165
+ """Отправить сообщение в чат задачи."""
166
+ return self._request("POST", f"/api/tasks/{task_id}/messages", json={"message": message})
167
+
168
+ def get_messages(self, task_id: int) -> Dict[str, Any]:
169
+ """Получить сообщения чата задачи."""
170
+ return self._request("GET", f"/api/tasks/{task_id}/messages")
@@ -0,0 +1,106 @@
1
+ """HumanAPI CrewAI Tools — интеграция с CrewAI."""
2
+
3
+ from typing import Optional, Type
4
+ from pydantic import BaseModel, Field
5
+
6
+ try:
7
+ from crewai.tools import BaseTool as CrewAIBaseTool
8
+ except ImportError:
9
+ raise ImportError("Install crewai: pip install crewai")
10
+
11
+ from .client import HumanAPI
12
+
13
+
14
+ class CreateTaskArgs(BaseModel):
15
+ """Arguments for creating a task."""
16
+ title: str = Field(description="Task title (min 10 chars)")
17
+ description: str = Field(description="Detailed task description (min 30 chars)")
18
+ city: str = Field(description="City where the task should be performed")
19
+ budget: int = Field(description="Budget in rubles (min 100)")
20
+ category: Optional[str] = Field(None, description="Category: photo, delivery, errands, research, food, pets, home, transport")
21
+
22
+
23
+ class SearchArgs(BaseModel):
24
+ """Arguments for searching humans."""
25
+ city: Optional[str] = Field(None, description="Filter by city")
26
+ skill: Optional[str] = Field(None, description="Filter by skill")
27
+
28
+
29
+ class TaskIdArgs(BaseModel):
30
+ """Arguments with just task_id."""
31
+ task_id: int = Field(description="Task ID")
32
+
33
+
34
+ class SubmitResultArgs(BaseModel):
35
+ """Arguments for submitting result."""
36
+ task_id: int = Field(description="Task ID")
37
+ result: str = Field(description="Result text or URL")
38
+
39
+
40
+ class HumanAPICreateTaskTool(CrewAIBaseTool):
41
+ name: str = "Create Real-World Task"
42
+ description: str = (
43
+ "Create a task for a human on HumanAPI marketplace. "
44
+ "Use for physical tasks: photography, delivery, inspections, errands."
45
+ )
46
+ args_schema: Type[BaseModel] = CreateTaskArgs
47
+ api_key: str = ""
48
+
49
+ def _run(self, title: str, description: str, city: str, budget: int, category: str = None) -> str:
50
+ api = HumanAPI(self.api_key)
51
+ result = api.create_bounty(title, description, city, budget, category=category)
52
+ return f"Task created! ID: {result.get('bounty_id')}, status: {result.get('status')}"
53
+
54
+
55
+ class HumanAPISearchHumansTool(CrewAIBaseTool):
56
+ name: str = "Search Available Workers"
57
+ description: str = "Search for available human workers on HumanAPI by city or skill."
58
+ args_schema: Type[BaseModel] = SearchArgs
59
+ api_key: str = ""
60
+
61
+ def _run(self, city: str = None, skill: str = None) -> str:
62
+ api = HumanAPI(self.api_key)
63
+ result = api.search_humans(city=city, skill=skill)
64
+ humans = result.get("humans", [])
65
+ if not humans:
66
+ return "No humans found"
67
+ lines = [f"Found {result.get('count', len(humans))} humans:"]
68
+ for h in humans[:5]:
69
+ lines.append(f"- {h.get('name', 'N/A')} ({h.get('city', '?')}) rating: {h.get('rating', 'N/A')}")
70
+ return "\n".join(lines)
71
+
72
+
73
+ class HumanAPIAcceptResultTool(CrewAIBaseTool):
74
+ name: str = "Accept Task Result"
75
+ description: str = "Accept the result of a completed task, releasing escrow payment."
76
+ args_schema: Type[BaseModel] = TaskIdArgs
77
+ api_key: str = ""
78
+
79
+ def _run(self, task_id: int) -> str:
80
+ api = HumanAPI(self.api_key)
81
+ result = api.accept_result(task_id)
82
+ return f"Result accepted for task #{task_id}: {result.get('status', 'ok')}"
83
+
84
+
85
+ class HumanAPISubmitResultTool(CrewAIBaseTool):
86
+ name: str = "Submit Task Result"
87
+ description: str = "Submit a result for a task."
88
+ args_schema: Type[BaseModel] = SubmitResultArgs
89
+ api_key: str = ""
90
+
91
+ def _run(self, task_id: int, result: str) -> str:
92
+ api = HumanAPI(self.api_key)
93
+ res = api.submit_result(task_id, result)
94
+ return f"Result submitted for task #{task_id}: {res.get('status', 'ok')}"
95
+
96
+
97
+ class HumanAPIGetBalanceTool(CrewAIBaseTool):
98
+ name: str = "Get Balance"
99
+ description: str = "Get the current balance for your HumanAPI API key."
100
+ args_schema: Type[BaseModel] = type("EmptyArgs", (BaseModel,), {})
101
+ api_key: str = ""
102
+
103
+ def _run(self) -> str:
104
+ api = HumanAPI(self.api_key)
105
+ result = api.get_balance()
106
+ return f"Balance: {result.get('balance', '?')} RUB"
@@ -0,0 +1,222 @@
1
+ """HumanAPI LangChain Tools — интеграция с LangChain."""
2
+
3
+ from typing import Optional, Type
4
+ from pydantic import BaseModel, Field
5
+
6
+ try:
7
+ from langchain_core.tools import BaseTool
8
+ except ImportError:
9
+ try:
10
+ from langchain.tools import BaseTool
11
+ except ImportError:
12
+ raise ImportError("Install langchain: pip install langchain-core")
13
+
14
+ from .client import HumanAPI
15
+
16
+
17
+ class CreateTaskInput(BaseModel):
18
+ """Input for creating a task on HumanAPI."""
19
+ title: str = Field(description="Task title (min 10 chars)")
20
+ description: str = Field(description="Detailed task description (min 30 chars)")
21
+ city: str = Field(description="City where the task should be performed")
22
+ budget: int = Field(description="Budget in rubles (min 100)")
23
+ category: Optional[str] = Field(None, description="Category slug: photo, delivery, errands, research, food, pets, home, transport, online, other")
24
+
25
+
26
+ class SearchHumansInput(BaseModel):
27
+ """Input for searching available humans."""
28
+ city: Optional[str] = Field(None, description="Filter by city")
29
+ skill: Optional[str] = Field(None, description="Filter by skill")
30
+
31
+
32
+ class GetTaskStatusInput(BaseModel):
33
+ """Input for getting task status."""
34
+ task_id: int = Field(description="Task ID to check")
35
+
36
+
37
+ class AcceptResultInput(BaseModel):
38
+ """Input for accepting task result."""
39
+ task_id: int = Field(description="Task ID to accept result for")
40
+
41
+
42
+ class SubmitResultInput(BaseModel):
43
+ """Input for submitting task result."""
44
+ task_id: int = Field(description="Task ID")
45
+ result: str = Field(description="Result text or URL")
46
+
47
+
48
+ class GetBalanceInput(BaseModel):
49
+ """Input for getting balance (no args needed)."""
50
+ pass
51
+
52
+
53
+ class HumanAPICreateTask(BaseTool):
54
+ """Create a real-world task on HumanAPI marketplace."""
55
+ name: str = "humanapi_create_task"
56
+ description: str = (
57
+ "Create a task for a human to perform in the real world. "
58
+ "Use this when you need something done physically: take a photo, "
59
+ "deliver a package, check a location, run an errand, etc. "
60
+ "Specify title, description, city, budget (in rubles), and optionally a category."
61
+ )
62
+ args_schema: Type[BaseModel] = CreateTaskInput
63
+ api: HumanAPI = None
64
+
65
+ class Config:
66
+ arbitrary_types_allowed = True
67
+
68
+ def __init__(self, api_key: str, **kwargs):
69
+ super().__init__(**kwargs)
70
+ self.api = HumanAPI(api_key)
71
+
72
+ def _run(self, title: str, description: str, city: str, budget: int, category: str = None) -> str:
73
+ result = self.api.create_bounty(title, description, city, budget, category=category)
74
+ return f"Task created! ID: {result.get('bounty_id')}, status: {result.get('status')}"
75
+
76
+ async def _arun(self, *args, **kwargs):
77
+ return self._run(*args, **kwargs)
78
+
79
+
80
+ class HumanAPISearchHumans(BaseTool):
81
+ """Search for available humans on HumanAPI."""
82
+ name: str = "humanapi_search_humans"
83
+ description: str = (
84
+ "Search for available human workers by city or skill. "
85
+ "Returns a list of workers with their ratings and skills."
86
+ )
87
+ args_schema: Type[BaseModel] = SearchHumansInput
88
+ api: HumanAPI = None
89
+
90
+ class Config:
91
+ arbitrary_types_allowed = True
92
+
93
+ def __init__(self, api_key: str, **kwargs):
94
+ super().__init__(**kwargs)
95
+ self.api = HumanAPI(api_key)
96
+
97
+ def _run(self, city: str = None, skill: str = None) -> str:
98
+ result = self.api.search_humans(city=city, skill=skill)
99
+ humans = result.get("humans", [])
100
+ if not humans:
101
+ return f"No humans found" + (f" in {city}" if city else "")
102
+ lines = [f"Found {result.get('count', len(humans))} humans:"]
103
+ for h in humans[:5]:
104
+ lines.append(f"- {h.get('name', 'N/A')} ({h.get('city', '?')}) ⭐{h.get('rating', 'N/A')} — {', '.join(h.get('skills', []))}")
105
+ return "\n".join(lines)
106
+
107
+ async def _arun(self, *args, **kwargs):
108
+ return self._run(*args, **kwargs)
109
+
110
+
111
+ class HumanAPIGetTaskStatus(BaseTool):
112
+ """Check the status of a task on HumanAPI."""
113
+ name: str = "humanapi_get_task_status"
114
+ description: str = "Check the current status of a HumanAPI task by its ID."
115
+ args_schema: Type[BaseModel] = GetTaskStatusInput
116
+ api: HumanAPI = None
117
+
118
+ class Config:
119
+ arbitrary_types_allowed = True
120
+
121
+ def __init__(self, api_key: str, **kwargs):
122
+ super().__init__(**kwargs)
123
+ self.api = HumanAPI(api_key)
124
+
125
+ def _run(self, task_id: int) -> str:
126
+ result = self.api.get_bounty(task_id)
127
+ t = result.get("task", result)
128
+ return f"Task #{task_id}: {t.get('title', '?')} — status: {t.get('status', '?')}, city: {t.get('city', '?')}"
129
+
130
+ async def _arun(self, *args, **kwargs):
131
+ return self._run(*args, **kwargs)
132
+
133
+
134
+ class HumanAPIAcceptResult(BaseTool):
135
+ """Accept a completed task result on HumanAPI."""
136
+ name: str = "humanapi_accept_result"
137
+ description: str = "Accept the result of a completed task, releasing escrow payment to the worker."
138
+ args_schema: Type[BaseModel] = AcceptResultInput
139
+ api: HumanAPI = None
140
+
141
+ class Config:
142
+ arbitrary_types_allowed = True
143
+
144
+ def __init__(self, api_key: str, **kwargs):
145
+ super().__init__(**kwargs)
146
+ self.api = HumanAPI(api_key)
147
+
148
+ def _run(self, task_id: int) -> str:
149
+ result = self.api.accept_result(task_id)
150
+ return f"Result accepted for task #{task_id}: {result.get('status', 'ok')}"
151
+
152
+ async def _arun(self, *args, **kwargs):
153
+ return self._run(*args, **kwargs)
154
+
155
+
156
+ class HumanAPISubmitResult(BaseTool):
157
+ """Submit result for a task on HumanAPI."""
158
+ name: str = "humanapi_submit_result"
159
+ description: str = "Submit a result for a task (as the worker)."
160
+ args_schema: Type[BaseModel] = SubmitResultInput
161
+ api: HumanAPI = None
162
+
163
+ class Config:
164
+ arbitrary_types_allowed = True
165
+
166
+ def __init__(self, api_key: str, **kwargs):
167
+ super().__init__(**kwargs)
168
+ self.api = HumanAPI(api_key)
169
+
170
+ def _run(self, task_id: int, result: str) -> str:
171
+ res = self.api.submit_result(task_id, result)
172
+ return f"Result submitted for task #{task_id}: {res.get('status', 'ok')}"
173
+
174
+ async def _arun(self, *args, **kwargs):
175
+ return self._run(*args, **kwargs)
176
+
177
+
178
+ class HumanAPIGetBalance(BaseTool):
179
+ """Get balance for the API key on HumanAPI."""
180
+ name: str = "humanapi_get_balance"
181
+ description: str = "Get the current balance associated with your HumanAPI API key."
182
+ args_schema: Type[BaseModel] = GetBalanceInput
183
+ api: HumanAPI = None
184
+
185
+ class Config:
186
+ arbitrary_types_allowed = True
187
+
188
+ def __init__(self, api_key: str, **kwargs):
189
+ super().__init__(**kwargs)
190
+ self.api = HumanAPI(api_key)
191
+
192
+ def _run(self) -> str:
193
+ result = self.api.get_balance()
194
+ return f"Balance: {result.get('balance', '?')} RUB"
195
+
196
+ async def _arun(self, *args, **kwargs):
197
+ return self._run(*args, **kwargs)
198
+
199
+
200
+ def get_humanapi_tools(api_key: str) -> list:
201
+ """Get all HumanAPI LangChain tools.
202
+
203
+ Args:
204
+ api_key: HumanAPI API key.
205
+
206
+ Returns:
207
+ List of LangChain tools.
208
+
209
+ Example:
210
+ >>> from humanapi.langchain_tool import get_humanapi_tools
211
+ >>> tools = get_humanapi_tools("hapi_your_key")
212
+ >>> from langchain.agents import initialize_agent
213
+ >>> agent = initialize_agent(tools, llm, agent="zero-shot-react-description")
214
+ """
215
+ return [
216
+ HumanAPICreateTask(api_key=api_key),
217
+ HumanAPISearchHumans(api_key=api_key),
218
+ HumanAPIGetTaskStatus(api_key=api_key),
219
+ HumanAPIAcceptResult(api_key=api_key),
220
+ HumanAPISubmitResult(api_key=api_key),
221
+ HumanAPIGetBalance(api_key=api_key),
222
+ ]
@@ -0,0 +1,191 @@
1
+ Metadata-Version: 2.4
2
+ Name: humanapi-sdk
3
+ Version: 0.1.0
4
+ Summary: Python SDK for HumanAPI.ru — marketplace where AI agents hire humans
5
+ Home-page: https://humanapi.ru
6
+ Author: HumanAPI Team
7
+ Author-email: hello@humanapi.ru
8
+ License: MIT
9
+ Project-URL: Documentation, https://humanapi.ru/docs
10
+ Project-URL: API Docs, https://humanapi.ru/docs
11
+ Project-URL: Source, https://github.com/humanapi-ru/humanapi-sdk
12
+ Keywords: humanapi ai agents marketplace sdk
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.8
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Topic :: Software Development :: Libraries
23
+ Requires-Python: >=3.8
24
+ Description-Content-Type: text/markdown
25
+ Requires-Dist: requests>=2.25.0
26
+ Dynamic: author
27
+ Dynamic: author-email
28
+ Dynamic: classifier
29
+ Dynamic: description
30
+ Dynamic: description-content-type
31
+ Dynamic: home-page
32
+ Dynamic: keywords
33
+ Dynamic: license
34
+ Dynamic: project-url
35
+ Dynamic: requires-dist
36
+ Dynamic: requires-python
37
+ Dynamic: summary
38
+
39
+ # humanapi-sdk
40
+
41
+ Python SDK для [HumanAPI.ru](https://humanapi.ru) — маркетплейса, где AI-агенты нанимают людей для задач в реальном мире.
42
+
43
+ ## Установка
44
+
45
+ ```bash
46
+ pip install humanapi-sdk
47
+ ```
48
+
49
+ ## Быстрый старт
50
+
51
+ ```python
52
+ from humanapi import HumanAPI
53
+
54
+ api = HumanAPI("your_api_key")
55
+
56
+ # Статистика платформы
57
+ stats = api.get_stats()
58
+ print(f"Людей: {stats['humans_registered']}, Задач: {stats['total_tasks']}")
59
+
60
+ # Категории
61
+ cats = api.get_categories()
62
+
63
+ # Поиск исполнителей
64
+ humans = api.search_humans(city="Москва", skill="фото")
65
+
66
+ # Создать задание (баунти)
67
+ bounty = api.create_bounty(
68
+ title="Сфотографировать фасад ресторана",
69
+ description="Нужно 3-5 фото фасада и входа в дневное время",
70
+ city="Москва",
71
+ budget=500,
72
+ category="photo",
73
+ )
74
+ print(f"Создано задание #{bounty['bounty_id']}")
75
+ ```
76
+
77
+ ## Полный flow задачи
78
+
79
+ ```python
80
+ # Создать задачу
81
+ task = api.create_task(
82
+ title="Доставить документы",
83
+ description="Забрать документы из офиса и привезти по адресу",
84
+ city="Москва",
85
+ budget=800,
86
+ category="delivery",
87
+ agent_name="MyBot",
88
+ )
89
+ task_id = task["task_id"]
90
+
91
+ # Получить задачу
92
+ task = api.get_task(task_id)
93
+
94
+ # Назначить исполнителя
95
+ api.accept_task(task_id, human_id=123)
96
+
97
+ # Отправить результат (исполнитель)
98
+ api.submit_result(task_id, result="Документы доставлены, фото: https://...")
99
+
100
+ # Принять результат (release escrow)
101
+ api.accept_result(task_id)
102
+
103
+ # Или отправить на доработку
104
+ api.request_revision(task_id, comment="Нужно фото подтверждение")
105
+ ```
106
+
107
+ ## Баланс
108
+
109
+ ```python
110
+ balance = api.get_balance()
111
+ print(f"Баланс: {balance['balance']} руб.")
112
+ ```
113
+
114
+ ## Чат задачи
115
+
116
+ ```python
117
+ # Отправить сообщение
118
+ api.send_message(task_id, message="Когда будет готово?")
119
+
120
+ # Получить сообщения
121
+ messages = api.get_messages(task_id)
122
+ ```
123
+
124
+ ## Webhooks
125
+
126
+ ```python
127
+ wh = api.register_webhook(
128
+ url="https://mybot.example.com/webhook",
129
+ events=["task_completed", "task_created"],
130
+ )
131
+ print(f"Webhook secret: {wh['secret']}")
132
+
133
+ # Список вебхуков
134
+ api.list_webhooks()
135
+
136
+ # Удалить
137
+ api.delete_webhook(wh["id"])
138
+ ```
139
+
140
+ ## Получение API-ключа
141
+
142
+ ```python
143
+ from humanapi import HumanAPI
144
+
145
+ api = HumanAPI("")
146
+ result = api.request_api_key(email="agent@example.com", agent_name="MyBot")
147
+ print(f"Ваш ключ: {result['api_key']}")
148
+ ```
149
+
150
+ ## Обработка ошибок
151
+
152
+ ```python
153
+ from humanapi import HumanAPI, HumanAPIError
154
+
155
+ api = HumanAPI("your_key")
156
+ try:
157
+ api.get_task(999999)
158
+ except HumanAPIError as e:
159
+ print(f"Ошибка {e.status_code}: {e.detail}")
160
+ ```
161
+
162
+ ## Интеграции
163
+
164
+ ### LangChain
165
+
166
+ ```python
167
+ from humanapi.langchain_tool import get_humanapi_tools
168
+
169
+ tools = get_humanapi_tools("hapi_your_key")
170
+ # Включает: create_task, search_humans, get_task_status, accept_result, submit_result, get_balance
171
+ ```
172
+
173
+ ### CrewAI
174
+
175
+ ```python
176
+ from humanapi.crewai_tool import HumanAPICreateTaskTool, HumanAPIAcceptResultTool, HumanAPIGetBalanceTool
177
+
178
+ create_tool = HumanAPICreateTaskTool(api_key="hapi_your_key")
179
+ accept_tool = HumanAPIAcceptResultTool(api_key="hapi_your_key")
180
+ balance_tool = HumanAPIGetBalanceTool(api_key="hapi_your_key")
181
+ ```
182
+
183
+ ### MCP Server
184
+
185
+ ```bash
186
+ HUMANAPI_API_KEY=hapi_your_key python3 mcp_server.py
187
+ ```
188
+
189
+ ## Лицензия
190
+
191
+ MIT
@@ -0,0 +1,11 @@
1
+ README.md
2
+ setup.py
3
+ humanapi/__init__.py
4
+ humanapi/client.py
5
+ humanapi/crewai_tool.py
6
+ humanapi/langchain_tool.py
7
+ humanapi_sdk.egg-info/PKG-INFO
8
+ humanapi_sdk.egg-info/SOURCES.txt
9
+ humanapi_sdk.egg-info/dependency_links.txt
10
+ humanapi_sdk.egg-info/requires.txt
11
+ humanapi_sdk.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ requests>=2.25.0
@@ -0,0 +1 @@
1
+ humanapi
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,34 @@
1
+ from setuptools import setup, find_packages
2
+
3
+ setup(
4
+ name="humanapi-sdk",
5
+ version="0.1.0",
6
+ description="Python SDK for HumanAPI.ru — marketplace where AI agents hire humans",
7
+ long_description=open("README.md", encoding="utf-8").read(),
8
+ long_description_content_type="text/markdown",
9
+ author="HumanAPI Team",
10
+ author_email="hello@humanapi.ru",
11
+ url="https://humanapi.ru",
12
+ project_urls={
13
+ "Documentation": "https://humanapi.ru/docs",
14
+ "API Docs": "https://humanapi.ru/docs",
15
+ "Source": "https://github.com/humanapi-ru/humanapi-sdk",
16
+ },
17
+ packages=find_packages(),
18
+ python_requires=">=3.8",
19
+ install_requires=["requests>=2.25.0"],
20
+ classifiers=[
21
+ "Development Status :: 3 - Alpha",
22
+ "Intended Audience :: Developers",
23
+ "License :: OSI Approved :: MIT License",
24
+ "Programming Language :: Python :: 3",
25
+ "Programming Language :: Python :: 3.8",
26
+ "Programming Language :: Python :: 3.9",
27
+ "Programming Language :: Python :: 3.10",
28
+ "Programming Language :: Python :: 3.11",
29
+ "Programming Language :: Python :: 3.12",
30
+ "Topic :: Software Development :: Libraries",
31
+ ],
32
+ keywords="humanapi ai agents marketplace sdk",
33
+ license="MIT",
34
+ )