construct-labs-crm-env 0.1.3__py3-none-any.whl → 0.1.7__py3-none-any.whl

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.
@@ -156,6 +156,7 @@ class CrmAgentEnv(EnvClient[CrmAgentAction, CrmAgentObservation, CrmAgentState])
156
156
  self._ws = ws_connect(
157
157
  self._ws_url,
158
158
  open_timeout=self._connect_timeout,
159
+ max_size=10 * 1024 * 1024,
159
160
  subprotocols=[auth_subprotocol],
160
161
  )
161
162
  except Exception as e:
@@ -226,40 +227,120 @@ class CrmAgentEnv(EnvClient[CrmAgentAction, CrmAgentObservation, CrmAgentState])
226
227
  Returns:
227
228
  The default system prompt string.
228
229
  """
229
- return """You are a tool-using agent interacting with a CRM (Customer Relationship Management) system.
230
+ # Define tool call examples as Python dicts - json.dumps ensures valid JSON
231
+ examples = {
232
+ "list_companies": {
233
+ "name": "list_companies",
234
+ "arguments": {"limit": 10},
235
+ },
236
+ "find_companies": {
237
+ "name": "list_companies",
238
+ "arguments": {"filter": 'name[ilike]:"%tech%"'},
239
+ },
240
+ "create_company": {
241
+ "name": "create_company",
242
+ "arguments": {
243
+ "company_name": "Acme Corp",
244
+ "company_domain": "acme.com",
245
+ },
246
+ },
247
+ "create_person": {
248
+ "name": "create_person",
249
+ "arguments": {
250
+ "person_first_name": "John",
251
+ "person_last_name": "Doe",
252
+ "person_email": "john@acme.com",
253
+ "person_company_id": "company-uuid-here",
254
+ },
255
+ },
256
+ "submit_answer": {
257
+ "name": "submit_answer",
258
+ "arguments": {
259
+ "answer": "The total pipeline value is $1.5M across 12 open opportunities."
260
+ },
261
+ },
262
+ }
263
+
264
+ return f"""You are a tool-using agent interacting with a CRM (Customer Relationship Management) system.
265
+
266
+ ## GOAL
267
+
268
+ Complete CRM tasks by creating, updating, retrieving, and managing business data.
269
+
270
+ ## DATA MODEL
271
+
272
+ - Companies: Organizations you do business with
273
+ - People: Contacts who work at companies (linked via person_company_id)
274
+ - Opportunities: Sales deals linked to a company and a person (point of contact)
275
+ - Notes: Free-text records attached to any company, person, or opportunity
276
+ - Tasks: Action items with due dates, attached to any company, person, or opportunity
277
+
278
+ ## AVAILABLE TOOLS
279
+
280
+ - Companies: list_companies, get_company, create_company, update_company, delete_company
281
+ - People: list_people, get_person, create_person, update_person, delete_person
282
+ - Opportunities: list_opportunities, get_opportunity, create_opportunity, update_opportunity, delete_opportunity
283
+ - Notes: list_notes, create_note
284
+ - Tasks: list_tasks, create_task, update_task, complete_task
285
+ - Answer: submit_answer
286
+
287
+ ## FILTERING AND PAGINATION
288
+
289
+ Use the filter parameter to search records. Format: field[comparator]:value
230
290
 
231
- GOAL: Complete CRM tasks by creating, updating, and managing business data.
291
+ Comparators: eq, neq, gt, gte, lt, lte, ilike (case-insensitive like), in, is, startsWith, containsAny
232
292
 
233
- AVAILABLE OPERATIONS:
234
- - Companies: list, get, create, update, delete
235
- - People/Contacts: list, get, create, update, delete
236
- - Opportunities: list, get, create, update, delete
237
- - Notes: list, create (attach to companies, people, or opportunities)
238
- - Tasks: list, create, update, complete
293
+ Examples:
294
+ - name[ilike]:"%acme%" - names containing "acme"
295
+ - stage[eq]:"WON" - opportunities with stage WON
296
+ - amount[gte]:10000 - deals worth $10,000 or more
297
+ - createdAt[gte]:"2026-01-01" - records created this year
298
+ - deletedAt[is]:NULL - non-deleted records
239
299
 
240
- EXAMPLES:
300
+ Rules: Quote strings and dates. Do not quote numbers. Combine with comma for AND: field1[eq]:"a",field2[gt]:5
241
301
 
242
- 1. List companies:
302
+ Pagination: Results return max 60 records. Use starting_after with the endCursor from pageInfo to get more.
303
+
304
+ ## WORKFLOW
305
+
306
+ For complex tasks, make multiple tool calls:
307
+ 1. First, list or search to find relevant records
308
+ 2. Then, get details or create/update as needed
309
+ 3. Finally, call submit_answer with your findings
310
+
311
+ ## OUTPUT FORMAT
312
+
313
+ Think briefly about which tool to use, then output exactly one tool call:
243
314
  <tool_call>
244
- {"name": "list_companies", "arguments": {"limit": 10}}
315
+ {{"name": "tool_name", "arguments": {{...}}}}
245
316
  </tool_call>
246
317
 
247
- 2. Create a company:
318
+ ## EXAMPLES
319
+
320
+ List companies:
248
321
  <tool_call>
249
- {"name": "create_company", "arguments": {"company_name": "Acme Corp", "company_domain": "acme.com"}}
322
+ {json.dumps(examples["list_companies"])}
250
323
  </tool_call>
251
324
 
252
- 3. Create a contact:
325
+ Find companies by name:
253
326
  <tool_call>
254
- {"name": "create_person", "arguments": {"person_first_name": "John", "person_last_name": "Doe", "person_email": "john@acme.com"}}
327
+ {json.dumps(examples["find_companies"])}
255
328
  </tool_call>
256
329
 
257
- 4. Submit final answer:
330
+ Create a company:
258
331
  <tool_call>
259
- {"name": "submit_answer", "arguments": {"answer": "The total pipeline value is $1.5M"}}
332
+ {json.dumps(examples["create_company"])}
260
333
  </tool_call>
261
334
 
262
- IMPORTANT: Output ONLY a tool_call, no other text."""
335
+ Create a contact linked to a company:
336
+ <tool_call>
337
+ {json.dumps(examples["create_person"])}
338
+ </tool_call>
339
+
340
+ Submit final answer:
341
+ <tool_call>
342
+ {json.dumps(examples["submit_answer"])}
343
+ </tool_call>"""
263
344
 
264
345
  @property
265
346
  def tools(self) -> list[JsonDict]:
@@ -17,35 +17,35 @@ LIST_COMPANIES: ToolDefinition = {
17
17
  "type": "function",
18
18
  "function": {
19
19
  "name": "list_companies",
20
- "description": "List all companies in the CRM",
20
+ "description": "List all companies in the CRM. Use filters to search by name, domain, or employee count. Response includes pageInfo with hasNextPage, startCursor, and endCursor for pagination.",
21
21
  "parameters": {
22
22
  "type": "object",
23
23
  "properties": {
24
24
  "limit": {
25
25
  "type": "integer",
26
26
  "default": 60,
27
- "description": "Maximum number of companies to return (max 200)",
27
+ "description": "Maximum number of companies to return (1-60). Default and max is 60.",
28
28
  },
29
29
  "starting_after": {
30
30
  "type": "string",
31
- "description": "Cursor for pagination - returns objects after this ID",
31
+ "description": "Cursor for forward pagination - returns companies after this cursor. Use endCursor from previous response's pageInfo.",
32
32
  },
33
33
  "ending_before": {
34
34
  "type": "string",
35
- "description": "Cursor for pagination - returns objects before this ID",
35
+ "description": "Cursor for backward pagination - returns companies before this cursor. Use startCursor from previous response's pageInfo.",
36
36
  },
37
37
  "order_by": {
38
38
  "type": "string",
39
- "description": "Order by: field_name[ASC|DESC]",
39
+ "description": "Sort order in format 'field[ASC|DESC]'. Examples: 'name[ASC]', 'createdAt[DESC]', 'employees[DESC]'.",
40
40
  },
41
41
  "filter": {
42
42
  "type": "string",
43
- "description": "Filter: field[eq|gt|lt|contains]:value",
43
+ "description": "Filter in format 'field[comparator]:value'. Comparators: eq, neq, gt, gte, lt, lte, in, is, like, ilike, startsWith, containsAny. Quote strings/dates, not numbers. Multiple conditions with comma (AND). Examples: 'name[ilike]:\"%acme%\"', 'employees[gte]:100', 'deletedAt[is]:NULL'. Advanced: 'or(status[eq]:\"active\",employees[gt]:50)'.",
44
44
  },
45
45
  "depth": {
46
46
  "type": "integer",
47
47
  "default": 1,
48
- "description": "Relation depth: 0=primary only, 1=include relations",
48
+ "description": "Relation depth: 0 returns only company fields, 1 includes related people and opportunities. Default is 1.",
49
49
  },
50
50
  },
51
51
  "required": [],
@@ -57,18 +57,18 @@ GET_COMPANY: ToolDefinition = {
57
57
  "type": "function",
58
58
  "function": {
59
59
  "name": "get_company",
60
- "description": "Get details of a specific company",
60
+ "description": "Get full details of a specific company by its ID, including related contacts and opportunities.",
61
61
  "parameters": {
62
62
  "type": "object",
63
63
  "properties": {
64
64
  "record_id": {
65
65
  "type": "string",
66
- "description": "ID of the company to retrieve",
66
+ "description": "The unique identifier (UUID) of the company to retrieve. Get this from list_companies.",
67
67
  },
68
68
  "depth": {
69
69
  "type": "integer",
70
70
  "default": 1,
71
- "description": "Relation depth: 0=primary only, 1=include relations",
71
+ "description": "Relation depth: 0 returns only company fields, 1 includes related people and opportunities. Default is 1.",
72
72
  },
73
73
  },
74
74
  "required": ["record_id"],
@@ -80,25 +80,25 @@ CREATE_COMPANY: ToolDefinition = {
80
80
  "type": "function",
81
81
  "function": {
82
82
  "name": "create_company",
83
- "description": "Create a new company in the CRM",
83
+ "description": "Create a new company in the CRM. Name is required; add domain, address, and employee count for a complete record.",
84
84
  "parameters": {
85
85
  "type": "object",
86
86
  "properties": {
87
87
  "company_name": {
88
88
  "type": "string",
89
- "description": "Name of the company",
89
+ "description": "The official name of the company (required). Example: 'Acme Corporation'.",
90
90
  },
91
91
  "company_domain": {
92
92
  "type": "string",
93
- "description": "Domain/website of the company",
93
+ "description": "The company's website domain without protocol. Example: 'acme.com' (not 'https://acme.com').",
94
94
  },
95
95
  "company_address": {
96
96
  "type": "string",
97
- "description": "Address of the company",
97
+ "description": "The company's physical address. Example: '123 Main St, San Francisco, CA 94102'.",
98
98
  },
99
99
  "company_employees": {
100
100
  "type": "integer",
101
- "description": "Number of employees",
101
+ "description": "Approximate number of employees at the company. Example: 250.",
102
102
  },
103
103
  },
104
104
  "required": ["company_name"],
@@ -110,18 +110,30 @@ UPDATE_COMPANY: ToolDefinition = {
110
110
  "type": "function",
111
111
  "function": {
112
112
  "name": "update_company",
113
- "description": "Update an existing company",
113
+ "description": "Update an existing company. Only include fields you want to change.",
114
114
  "parameters": {
115
115
  "type": "object",
116
116
  "properties": {
117
117
  "record_id": {
118
118
  "type": "string",
119
- "description": "ID of the company to update",
119
+ "description": "The unique identifier (UUID) of the company to update. Get this from list_companies or get_company.",
120
+ },
121
+ "company_name": {
122
+ "type": "string",
123
+ "description": "New name for the company. Leave out to keep unchanged.",
124
+ },
125
+ "company_domain": {
126
+ "type": "string",
127
+ "description": "New website domain (e.g., 'acme.com'). Leave out to keep unchanged.",
128
+ },
129
+ "company_address": {
130
+ "type": "string",
131
+ "description": "New physical address. Leave out to keep unchanged.",
132
+ },
133
+ "company_employees": {
134
+ "type": "integer",
135
+ "description": "Updated employee count. Leave out to keep unchanged.",
120
136
  },
121
- "company_name": {"type": "string"},
122
- "company_domain": {"type": "string"},
123
- "company_address": {"type": "string"},
124
- "company_employees": {"type": "integer"},
125
137
  },
126
138
  "required": ["record_id"],
127
139
  },
@@ -132,13 +144,13 @@ DELETE_COMPANY: ToolDefinition = {
132
144
  "type": "function",
133
145
  "function": {
134
146
  "name": "delete_company",
135
- "description": "Delete a company from the CRM",
147
+ "description": "Permanently delete a company from the CRM. This may also affect related contacts and opportunities.",
136
148
  "parameters": {
137
149
  "type": "object",
138
150
  "properties": {
139
151
  "record_id": {
140
152
  "type": "string",
141
- "description": "ID of the company to delete",
153
+ "description": "The unique identifier (UUID) of the company to delete. Get this from list_companies or get_company. This action cannot be undone.",
142
154
  },
143
155
  },
144
156
  "required": ["record_id"],
@@ -154,20 +166,36 @@ LIST_PEOPLE: ToolDefinition = {
154
166
  "type": "function",
155
167
  "function": {
156
168
  "name": "list_people",
157
- "description": "List all contacts/people in the CRM",
169
+ "description": "List all contacts/people in the CRM. Use filters to search by name, email, company, or job title. Response includes pageInfo with hasNextPage, startCursor, and endCursor for pagination.",
158
170
  "parameters": {
159
171
  "type": "object",
160
172
  "properties": {
161
173
  "limit": {
162
174
  "type": "integer",
163
175
  "default": 60,
164
- "description": "Maximum number of contacts to return (max 200)",
176
+ "description": "Maximum number of contacts to return (1-60). Default and max is 60.",
177
+ },
178
+ "starting_after": {
179
+ "type": "string",
180
+ "description": "Cursor for forward pagination - returns contacts after this cursor. Use endCursor from previous response's pageInfo.",
181
+ },
182
+ "ending_before": {
183
+ "type": "string",
184
+ "description": "Cursor for backward pagination - returns contacts before this cursor. Use startCursor from previous response's pageInfo.",
185
+ },
186
+ "order_by": {
187
+ "type": "string",
188
+ "description": "Sort order in format 'field[ASC|DESC]'. Examples: 'name.firstName[ASC]', 'createdAt[DESC]', 'email[ASC]'.",
189
+ },
190
+ "filter": {
191
+ "type": "string",
192
+ "description": "Filter in format 'field[comparator]:value'. Comparators: eq, neq, gt, gte, lt, lte, in, is, like, ilike, startsWith, containsAny. Quote strings/dates, not numbers. Use dot notation for nested fields. Examples: 'email[ilike]:\"%@acme.com\"', 'name.firstName[eq]:\"John\"', 'company.name[ilike]:\"%tech%\"'. Advanced: 'or(jobTitle[ilike]:\"%CEO%\",jobTitle[ilike]:\"%CTO%\")'.",
193
+ },
194
+ "depth": {
195
+ "type": "integer",
196
+ "default": 1,
197
+ "description": "Relation depth: 0 returns only person fields, 1 includes related company data. Default is 1.",
165
198
  },
166
- "starting_after": {"type": "string"},
167
- "ending_before": {"type": "string"},
168
- "order_by": {"type": "string"},
169
- "filter": {"type": "string"},
170
- "depth": {"type": "integer", "default": 1},
171
199
  },
172
200
  "required": [],
173
201
  },
@@ -178,15 +206,19 @@ GET_PERSON: ToolDefinition = {
178
206
  "type": "function",
179
207
  "function": {
180
208
  "name": "get_person",
181
- "description": "Get details of a specific contact",
209
+ "description": "Get full details of a specific contact/person by their ID.",
182
210
  "parameters": {
183
211
  "type": "object",
184
212
  "properties": {
185
213
  "record_id": {
186
214
  "type": "string",
187
- "description": "ID of the contact to retrieve",
215
+ "description": "The unique identifier (UUID) of the contact to retrieve. Get this from list_people.",
216
+ },
217
+ "depth": {
218
+ "type": "integer",
219
+ "default": 1,
220
+ "description": "Relation depth: 0 returns only person fields, 1 includes related company and opportunity data. Default is 1.",
188
221
  },
189
- "depth": {"type": "integer", "default": 1},
190
222
  },
191
223
  "required": ["record_id"],
192
224
  },
@@ -197,33 +229,33 @@ CREATE_PERSON: ToolDefinition = {
197
229
  "type": "function",
198
230
  "function": {
199
231
  "name": "create_person",
200
- "description": "Create a new contact/person in the CRM",
232
+ "description": "Create a new contact/person in the CRM. First and last name are required; other fields are optional.",
201
233
  "parameters": {
202
234
  "type": "object",
203
235
  "properties": {
204
236
  "person_first_name": {
205
237
  "type": "string",
206
- "description": "First name",
238
+ "description": "The contact's first name (required).",
207
239
  },
208
240
  "person_last_name": {
209
241
  "type": "string",
210
- "description": "Last name",
242
+ "description": "The contact's last name (required).",
211
243
  },
212
244
  "person_email": {
213
245
  "type": "string",
214
- "description": "Email address",
246
+ "description": "The contact's email address. Format: 'user@domain.com'.",
215
247
  },
216
248
  "person_phone": {
217
249
  "type": "string",
218
- "description": "Phone number",
250
+ "description": "The contact's phone number. Any format accepted (e.g., '+1-555-123-4567').",
219
251
  },
220
252
  "person_company_id": {
221
253
  "type": "string",
222
- "description": "ID of associated company",
254
+ "description": "UUID of the company this person works for. Get this from list_companies or create_company.",
223
255
  },
224
256
  "person_job_title": {
225
257
  "type": "string",
226
- "description": "Job title",
258
+ "description": "The contact's job title or role (e.g., 'CEO', 'Sales Manager', 'Software Engineer').",
227
259
  },
228
260
  },
229
261
  "required": ["person_first_name", "person_last_name"],
@@ -235,19 +267,34 @@ UPDATE_PERSON: ToolDefinition = {
235
267
  "type": "function",
236
268
  "function": {
237
269
  "name": "update_person",
238
- "description": "Update an existing contact",
270
+ "description": "Update an existing contact. Only include fields you want to change.",
239
271
  "parameters": {
240
272
  "type": "object",
241
273
  "properties": {
242
274
  "record_id": {
243
275
  "type": "string",
244
- "description": "ID of the contact to update",
276
+ "description": "The unique identifier (UUID) of the contact to update. Get this from list_people or get_person.",
277
+ },
278
+ "person_first_name": {
279
+ "type": "string",
280
+ "description": "New first name. Leave out to keep unchanged.",
281
+ },
282
+ "person_last_name": {
283
+ "type": "string",
284
+ "description": "New last name. Leave out to keep unchanged.",
285
+ },
286
+ "person_email": {
287
+ "type": "string",
288
+ "description": "New email address. Leave out to keep unchanged.",
289
+ },
290
+ "person_phone": {
291
+ "type": "string",
292
+ "description": "New phone number. Leave out to keep unchanged.",
293
+ },
294
+ "person_job_title": {
295
+ "type": "string",
296
+ "description": "New job title. Leave out to keep unchanged.",
245
297
  },
246
- "person_first_name": {"type": "string"},
247
- "person_last_name": {"type": "string"},
248
- "person_email": {"type": "string"},
249
- "person_phone": {"type": "string"},
250
- "person_job_title": {"type": "string"},
251
298
  },
252
299
  "required": ["record_id"],
253
300
  },
@@ -258,13 +305,13 @@ DELETE_PERSON: ToolDefinition = {
258
305
  "type": "function",
259
306
  "function": {
260
307
  "name": "delete_person",
261
- "description": "Delete a contact from the CRM",
308
+ "description": "Permanently delete a contact/person from the CRM. This may also affect related opportunities and notes.",
262
309
  "parameters": {
263
310
  "type": "object",
264
311
  "properties": {
265
312
  "record_id": {
266
313
  "type": "string",
267
- "description": "ID of the contact to delete",
314
+ "description": "The unique identifier (UUID) of the contact to delete. Get this from list_people or get_person. This action cannot be undone.",
268
315
  },
269
316
  },
270
317
  "required": ["record_id"],
@@ -280,20 +327,36 @@ LIST_OPPORTUNITIES: ToolDefinition = {
280
327
  "type": "function",
281
328
  "function": {
282
329
  "name": "list_opportunities",
283
- "description": "List all opportunities/deals in the CRM",
330
+ "description": "List all opportunities/deals in the CRM. Use filters to search by stage, amount, company, or close date. Response includes pageInfo with hasNextPage, startCursor, and endCursor for pagination.",
284
331
  "parameters": {
285
332
  "type": "object",
286
333
  "properties": {
287
334
  "limit": {
288
335
  "type": "integer",
289
336
  "default": 60,
290
- "description": "Maximum number to return (max 200)",
337
+ "description": "Maximum number of opportunities to return (1-60). Default and max is 60.",
338
+ },
339
+ "starting_after": {
340
+ "type": "string",
341
+ "description": "Cursor for forward pagination - returns opportunities after this cursor. Use endCursor from previous response's pageInfo.",
342
+ },
343
+ "ending_before": {
344
+ "type": "string",
345
+ "description": "Cursor for backward pagination - returns opportunities before this cursor. Use startCursor from previous response's pageInfo.",
346
+ },
347
+ "order_by": {
348
+ "type": "string",
349
+ "description": "Sort order in format 'field[ASC|DESC]'. Examples: 'amount[DESC]', 'closeDate[ASC]', 'stage[ASC]'.",
350
+ },
351
+ "filter": {
352
+ "type": "string",
353
+ "description": "Filter in format 'field[comparator]:value'. Comparators: eq, neq, gt, gte, lt, lte, in, is, like, ilike, startsWith, containsAny. Quote strings/dates, not numbers. Examples: 'stage[eq]:\"WON\"', 'amount[gte]:10000', 'closeDate[gte]:\"2026-01-01\"', 'company.name[ilike]:\"%acme%\"'. Advanced: 'or(stage[eq]:\"WON\",stage[eq]:\"PROPOSAL\")'.",
354
+ },
355
+ "depth": {
356
+ "type": "integer",
357
+ "default": 1,
358
+ "description": "Relation depth: 0 returns only opportunity fields, 1 includes related company and person data. Default is 1.",
291
359
  },
292
- "starting_after": {"type": "string"},
293
- "ending_before": {"type": "string"},
294
- "order_by": {"type": "string"},
295
- "filter": {"type": "string"},
296
- "depth": {"type": "integer", "default": 1},
297
360
  },
298
361
  "required": [],
299
362
  },
@@ -304,15 +367,19 @@ GET_OPPORTUNITY: ToolDefinition = {
304
367
  "type": "function",
305
368
  "function": {
306
369
  "name": "get_opportunity",
307
- "description": "Get details of a specific opportunity",
370
+ "description": "Get full details of a specific opportunity/deal by its ID.",
308
371
  "parameters": {
309
372
  "type": "object",
310
373
  "properties": {
311
374
  "record_id": {
312
375
  "type": "string",
313
- "description": "ID of the opportunity",
376
+ "description": "The unique identifier (UUID) of the opportunity to retrieve. Get this from list_opportunities.",
377
+ },
378
+ "depth": {
379
+ "type": "integer",
380
+ "default": 1,
381
+ "description": "Relation depth: 0 returns only opportunity fields, 1 includes related company and person data. Default is 1.",
314
382
  },
315
- "depth": {"type": "integer", "default": 1},
316
383
  },
317
384
  "required": ["record_id"],
318
385
  },
@@ -323,34 +390,34 @@ CREATE_OPPORTUNITY: ToolDefinition = {
323
390
  "type": "function",
324
391
  "function": {
325
392
  "name": "create_opportunity",
326
- "description": "Create a new opportunity/deal",
393
+ "description": "Create a new sales opportunity/deal in the CRM. Name is required; link to company and contact for full tracking.",
327
394
  "parameters": {
328
395
  "type": "object",
329
396
  "properties": {
330
397
  "opportunity_name": {
331
398
  "type": "string",
332
- "description": "Name of the opportunity",
399
+ "description": "A descriptive name for the deal (required). Example: 'Acme Corp - Enterprise License Q1'.",
333
400
  },
334
401
  "opportunity_amount": {
335
402
  "type": "number",
336
- "description": "Deal value",
403
+ "description": "The monetary value of the deal in dollars. Example: 50000 for a $50,000 deal.",
337
404
  },
338
405
  "opportunity_stage": {
339
406
  "type": "string",
340
407
  "enum": ["NEW", "MEETING", "PROPOSAL", "WON", "LOST"],
341
- "description": "Sales stage",
408
+ "description": "Current stage in the sales pipeline. NEW: initial lead, MEETING: scheduled/had meeting, PROPOSAL: sent proposal, WON: closed won, LOST: closed lost.",
342
409
  },
343
410
  "opportunity_close_date": {
344
411
  "type": "string",
345
- "description": "Expected close date (ISO format)",
412
+ "description": "Expected or actual close date in ISO 8601 format. Example: '2026-03-15' or '2026-03-15T00:00:00Z'.",
346
413
  },
347
414
  "opportunity_company_id": {
348
415
  "type": "string",
349
- "description": "Associated company ID",
416
+ "description": "UUID of the company this opportunity is with. Get this from list_companies or create_company.",
350
417
  },
351
418
  "opportunity_person_id": {
352
419
  "type": "string",
353
- "description": "Point of contact ID",
420
+ "description": "UUID of the primary contact/person for this deal. Get this from list_people or create_person.",
354
421
  },
355
422
  },
356
423
  "required": ["opportunity_name"],
@@ -362,21 +429,31 @@ UPDATE_OPPORTUNITY: ToolDefinition = {
362
429
  "type": "function",
363
430
  "function": {
364
431
  "name": "update_opportunity",
365
- "description": "Update an existing opportunity",
432
+ "description": "Update an existing opportunity. Only include fields you want to change. Use this to advance deals through the pipeline.",
366
433
  "parameters": {
367
434
  "type": "object",
368
435
  "properties": {
369
436
  "record_id": {
370
437
  "type": "string",
371
- "description": "ID of the opportunity to update",
438
+ "description": "The unique identifier (UUID) of the opportunity to update. Get this from list_opportunities or get_opportunity.",
439
+ },
440
+ "opportunity_name": {
441
+ "type": "string",
442
+ "description": "New name for the opportunity. Leave out to keep unchanged.",
443
+ },
444
+ "opportunity_amount": {
445
+ "type": "number",
446
+ "description": "Updated deal value in dollars. Leave out to keep unchanged.",
372
447
  },
373
- "opportunity_name": {"type": "string"},
374
- "opportunity_amount": {"type": "number"},
375
448
  "opportunity_stage": {
376
449
  "type": "string",
377
450
  "enum": ["NEW", "MEETING", "PROPOSAL", "WON", "LOST"],
451
+ "description": "New pipeline stage. NEW: initial lead, MEETING: scheduled/had meeting, PROPOSAL: sent proposal, WON: closed won, LOST: closed lost.",
452
+ },
453
+ "opportunity_close_date": {
454
+ "type": "string",
455
+ "description": "Updated close date in ISO 8601 format (e.g., '2026-03-15'). Leave out to keep unchanged.",
378
456
  },
379
- "opportunity_close_date": {"type": "string"},
380
457
  },
381
458
  "required": ["record_id"],
382
459
  },
@@ -387,13 +464,13 @@ DELETE_OPPORTUNITY: ToolDefinition = {
387
464
  "type": "function",
388
465
  "function": {
389
466
  "name": "delete_opportunity",
390
- "description": "Delete an opportunity",
467
+ "description": "Permanently delete an opportunity/deal from the CRM. Consider marking as LOST instead to preserve history.",
391
468
  "parameters": {
392
469
  "type": "object",
393
470
  "properties": {
394
471
  "record_id": {
395
472
  "type": "string",
396
- "description": "ID of the opportunity to delete",
473
+ "description": "The unique identifier (UUID) of the opportunity to delete. Get this from list_opportunities or get_opportunity. This action cannot be undone.",
397
474
  },
398
475
  },
399
476
  "required": ["record_id"],
@@ -409,14 +486,14 @@ LIST_NOTES: ToolDefinition = {
409
486
  "type": "function",
410
487
  "function": {
411
488
  "name": "list_notes",
412
- "description": "List all notes in the CRM",
489
+ "description": "List all notes in the CRM. Notes are attached to companies, people, or opportunities and contain meeting summaries, call logs, and updates.",
413
490
  "parameters": {
414
491
  "type": "object",
415
492
  "properties": {
416
493
  "limit": {
417
494
  "type": "integer",
418
495
  "default": 10,
419
- "description": "Maximum number of notes to return",
496
+ "description": "Maximum number of notes to return. Default is 10. Use higher values to see more history.",
420
497
  },
421
498
  },
422
499
  "required": [],
@@ -428,22 +505,22 @@ CREATE_NOTE: ToolDefinition = {
428
505
  "type": "function",
429
506
  "function": {
430
507
  "name": "create_note",
431
- "description": "Create a note attached to a record",
508
+ "description": "Create a note attached to a company, person, or opportunity. Use for meeting notes, call logs, important updates.",
432
509
  "parameters": {
433
510
  "type": "object",
434
511
  "properties": {
435
512
  "note_body": {
436
513
  "type": "string",
437
- "description": "Content of the note",
514
+ "description": "The text content of the note (required). Can include meeting summaries, call notes, action items, etc.",
438
515
  },
439
516
  "note_target_id": {
440
517
  "type": "string",
441
- "description": "ID of record to attach note to",
518
+ "description": "UUID of the record to attach this note to. Get from list_companies, list_people, or list_opportunities.",
442
519
  },
443
520
  "note_target_type": {
444
521
  "type": "string",
445
522
  "enum": ["company", "person", "opportunity"],
446
- "description": "Type of record",
523
+ "description": "The type of record to attach to: 'company', 'person', or 'opportunity'. Must match the type of note_target_id.",
447
524
  },
448
525
  },
449
526
  "required": ["note_body"],
@@ -459,14 +536,14 @@ LIST_TASKS: ToolDefinition = {
459
536
  "type": "function",
460
537
  "function": {
461
538
  "name": "list_tasks",
462
- "description": "List all tasks in the CRM",
539
+ "description": "List all tasks in the CRM. Tasks represent follow-ups, reminders, and action items that may be linked to companies, people, or opportunities.",
463
540
  "parameters": {
464
541
  "type": "object",
465
542
  "properties": {
466
543
  "limit": {
467
544
  "type": "integer",
468
545
  "default": 10,
469
- "description": "Maximum number of tasks to return",
546
+ "description": "Maximum number of tasks to return. Default is 10. Use higher values to see more tasks.",
470
547
  },
471
548
  },
472
549
  "required": [],
@@ -478,35 +555,35 @@ CREATE_TASK: ToolDefinition = {
478
555
  "type": "function",
479
556
  "function": {
480
557
  "name": "create_task",
481
- "description": "Create a task, optionally linked to a record",
558
+ "description": "Create a follow-up task, optionally linked to a company, person, or opportunity. Use for reminders, action items, and scheduled activities.",
482
559
  "parameters": {
483
560
  "type": "object",
484
561
  "properties": {
485
562
  "task_title": {
486
563
  "type": "string",
487
- "description": "Title of the task",
564
+ "description": "Short title describing the task (required). Example: 'Follow up on proposal', 'Schedule demo call'.",
488
565
  },
489
566
  "task_body": {
490
567
  "type": "string",
491
- "description": "Description",
568
+ "description": "Detailed description of what needs to be done. Include context, steps, or relevant information.",
492
569
  },
493
570
  "task_due_date": {
494
571
  "type": "string",
495
- "description": "Due date (ISO format)",
572
+ "description": "When the task should be completed, in ISO 8601 format. Example: '2026-02-15' or '2026-02-15T14:00:00Z'.",
496
573
  },
497
574
  "task_status": {
498
575
  "type": "string",
499
576
  "enum": ["TODO", "IN_PROGRESS", "DONE"],
500
- "description": "Status",
577
+ "description": "Current status: TODO (not started), IN_PROGRESS (being worked on), DONE (completed). Defaults to TODO if not specified.",
501
578
  },
502
579
  "task_target_id": {
503
580
  "type": "string",
504
- "description": "ID of record to link task to",
581
+ "description": "UUID of the record to link this task to. Get from list_companies, list_people, or list_opportunities.",
505
582
  },
506
583
  "task_target_type": {
507
584
  "type": "string",
508
585
  "enum": ["company", "person", "opportunity"],
509
- "description": "Type of record",
586
+ "description": "The type of record to link to: 'company', 'person', or 'opportunity'. Must match the type of task_target_id.",
510
587
  },
511
588
  },
512
589
  "required": ["task_title"],
@@ -518,17 +595,26 @@ UPDATE_TASK: ToolDefinition = {
518
595
  "type": "function",
519
596
  "function": {
520
597
  "name": "update_task",
521
- "description": "Update an existing task",
598
+ "description": "Update an existing task. Only include fields you want to change. Use complete_task to mark as done.",
522
599
  "parameters": {
523
600
  "type": "object",
524
601
  "properties": {
525
602
  "record_id": {
526
603
  "type": "string",
527
- "description": "ID of the task to update",
604
+ "description": "The unique identifier (UUID) of the task to update. Get this from list_tasks.",
605
+ },
606
+ "task_title": {
607
+ "type": "string",
608
+ "description": "New title for the task. Leave out to keep unchanged.",
609
+ },
610
+ "task_body": {
611
+ "type": "string",
612
+ "description": "New description for the task. Leave out to keep unchanged.",
613
+ },
614
+ "task_due_date": {
615
+ "type": "string",
616
+ "description": "New due date in ISO 8601 format (e.g., '2026-02-15'). Leave out to keep unchanged.",
528
617
  },
529
- "task_title": {"type": "string"},
530
- "task_body": {"type": "string"},
531
- "task_due_date": {"type": "string"},
532
618
  },
533
619
  "required": ["record_id"],
534
620
  },
@@ -539,13 +625,13 @@ COMPLETE_TASK: ToolDefinition = {
539
625
  "type": "function",
540
626
  "function": {
541
627
  "name": "complete_task",
542
- "description": "Mark a task as complete",
628
+ "description": "Mark a task as complete (sets status to DONE). Use this when a task has been finished.",
543
629
  "parameters": {
544
630
  "type": "object",
545
631
  "properties": {
546
632
  "record_id": {
547
633
  "type": "string",
548
- "description": "ID of the task to complete",
634
+ "description": "The unique identifier (UUID) of the task to mark as complete. Get this from list_tasks.",
549
635
  },
550
636
  },
551
637
  "required": ["record_id"],
@@ -561,13 +647,13 @@ SUBMIT_ANSWER: ToolDefinition = {
561
647
  "type": "function",
562
648
  "function": {
563
649
  "name": "submit_answer",
564
- "description": "Submit final answer and end the session",
650
+ "description": "Submit your final answer to complete the task. Call this when you have gathered all necessary information and are ready to respond. This ends the session.",
565
651
  "parameters": {
566
652
  "type": "object",
567
653
  "properties": {
568
654
  "answer": {
569
655
  "type": "string",
570
- "description": "The final answer based on CRM data",
656
+ "description": "Your complete answer to the user's question, based on the CRM data you retrieved. Be specific and include relevant details like names, amounts, dates, or counts.",
571
657
  },
572
658
  },
573
659
  "required": ["answer"],
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: construct-labs-crm-env
3
- Version: 0.1.3
3
+ Version: 0.1.7
4
4
  Summary: CRM Agent Environment SDK by Construct Labs - Train RL agents to interact with CRM systems
5
5
  Project-URL: Homepage, https://construct-labs.com
6
6
  Author-email: Construct Labs GmbH <hello@construct-labs.com>
@@ -0,0 +1,10 @@
1
+ construct_labs_crm_env/__init__.py,sha256=XRei6wERXV6MMV168AkgeAMlsZLRSdXA2pPg8icfWQ4,917
2
+ construct_labs_crm_env/client.py,sha256=aqixV5860Xkh4pSLVOGoXTDVJ6jxENOthtlrxQc3DFo,21673
3
+ construct_labs_crm_env/models.py,sha256=bs-n9FcWcR8DqKvurmm0wUebWBWp9hG6Zaj6s7jEptg,9200
4
+ construct_labs_crm_env/protocol.py,sha256=h_7-0XaV9gBNHiSXoW4aITSD9K21R1Swc5yZR6LF50A,671
5
+ construct_labs_crm_env/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ construct_labs_crm_env/tools.py,sha256=dvW8O8fp2gCXGm3hMv-7Nd9mu4d6eUV7Q9ropuDKu_o,29237
7
+ construct_labs_crm_env-0.1.7.dist-info/METADATA,sha256=b3fzLHEnIr31iJznIrZISG0iX5SokOqyNDcmjywyt5w,11923
8
+ construct_labs_crm_env-0.1.7.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
9
+ construct_labs_crm_env-0.1.7.dist-info/licenses/LICENSE,sha256=zPT_KqeG9QTE0zTfKGheMHluFJB1fn_bNgNehnnpXGM,2210
10
+ construct_labs_crm_env-0.1.7.dist-info/RECORD,,
@@ -1,10 +0,0 @@
1
- construct_labs_crm_env/__init__.py,sha256=XRei6wERXV6MMV168AkgeAMlsZLRSdXA2pPg8icfWQ4,917
2
- construct_labs_crm_env/client.py,sha256=OPXcNT1QTNST_-OdI1jQtcVVrdIQKmmpH5JmJCNVS14,18980
3
- construct_labs_crm_env/models.py,sha256=bs-n9FcWcR8DqKvurmm0wUebWBWp9hG6Zaj6s7jEptg,9200
4
- construct_labs_crm_env/protocol.py,sha256=h_7-0XaV9gBNHiSXoW4aITSD9K21R1Swc5yZR6LF50A,671
5
- construct_labs_crm_env/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- construct_labs_crm_env/tools.py,sha256=zdYlJfTr5d3El9awlg-VeTommJ6nCNAd13E09drxv8E,18854
7
- construct_labs_crm_env-0.1.3.dist-info/METADATA,sha256=oPrpeZNalu8QgHjAF34NgyO6vIvrrfp_1Le5TfVraAU,11923
8
- construct_labs_crm_env-0.1.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
9
- construct_labs_crm_env-0.1.3.dist-info/licenses/LICENSE,sha256=zPT_KqeG9QTE0zTfKGheMHluFJB1fn_bNgNehnnpXGM,2210
10
- construct_labs_crm_env-0.1.3.dist-info/RECORD,,