construct-labs-crm-env 0.1.2__py3-none-any.whl → 0.1.3__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.
- construct_labs_crm_env/__init__.py +7 -2
- construct_labs_crm_env/client.py +63 -553
- construct_labs_crm_env/tools.py +611 -0
- {construct_labs_crm_env-0.1.2.dist-info → construct_labs_crm_env-0.1.3.dist-info}/METADATA +1 -1
- construct_labs_crm_env-0.1.3.dist-info/RECORD +10 -0
- construct_labs_crm_env-0.1.3.dist-info/licenses/LICENSE +56 -0
- construct_labs_crm_env-0.1.2.dist-info/RECORD +0 -9
- construct_labs_crm_env-0.1.2.dist-info/licenses/LICENSE +0 -42
- {construct_labs_crm_env-0.1.2.dist-info → construct_labs_crm_env-0.1.3.dist-info}/WHEEL +0 -0
construct_labs_crm_env/client.py
CHANGED
|
@@ -35,6 +35,7 @@ from .models import (
|
|
|
35
35
|
CrmAgentState,
|
|
36
36
|
)
|
|
37
37
|
from .protocol import ParsedAction
|
|
38
|
+
from .tools import DEFAULT_TOOLS
|
|
38
39
|
|
|
39
40
|
# Type alias for JSON-serializable dictionaries
|
|
40
41
|
JsonDict = dict[str, Any]
|
|
@@ -105,7 +106,7 @@ class CrmAgentEnv(EnvClient[CrmAgentAction, CrmAgentObservation, CrmAgentState])
|
|
|
105
106
|
raise ValueError(
|
|
106
107
|
"API key is required. Pass api_key parameter or set "
|
|
107
108
|
"CRM_AGENT_API_KEY environment variable. "
|
|
108
|
-
"
|
|
109
|
+
"Contact hello@construct-labs.com to obtain an API key."
|
|
109
110
|
)
|
|
110
111
|
|
|
111
112
|
self._api_key = resolved_api_key
|
|
@@ -162,7 +163,7 @@ class CrmAgentEnv(EnvClient[CrmAgentAction, CrmAgentObservation, CrmAgentState])
|
|
|
162
163
|
if "401" in error_msg or "403" in error_msg or "4001" in error_msg:
|
|
163
164
|
raise ConnectionError(
|
|
164
165
|
"Authentication failed. Please verify your API key. "
|
|
165
|
-
"
|
|
166
|
+
"Contact hello@construct-labs.com if you need assistance."
|
|
166
167
|
) from e
|
|
167
168
|
raise ConnectionError(f"Failed to connect to {self._ws_url}: {e}") from e
|
|
168
169
|
finally:
|
|
@@ -194,12 +195,6 @@ class CrmAgentEnv(EnvClient[CrmAgentAction, CrmAgentObservation, CrmAgentState])
|
|
|
194
195
|
"""Parse server response into CrmAgentState."""
|
|
195
196
|
return CrmAgentState.model_validate(payload)
|
|
196
197
|
|
|
197
|
-
def _reset_payload(self, seed: int | None = None) -> JsonDict:
|
|
198
|
-
"""Create payload for reset request."""
|
|
199
|
-
if seed is not None:
|
|
200
|
-
return {"seed": seed}
|
|
201
|
-
return {}
|
|
202
|
-
|
|
203
198
|
# =========================================================================
|
|
204
199
|
# Extensible Properties - Override these in subclasses
|
|
205
200
|
# =========================================================================
|
|
@@ -270,11 +265,12 @@ IMPORTANT: Output ONLY a tool_call, no other text."""
|
|
|
270
265
|
def tools(self) -> list[JsonDict]:
|
|
271
266
|
"""Tool definitions for the CRM environment.
|
|
272
267
|
|
|
273
|
-
|
|
274
|
-
|
|
268
|
+
Returns tool definitions formatted by `format_tools()`. Override
|
|
269
|
+
`format_tools()` to transform the tool schema for different providers
|
|
270
|
+
(e.g., Anthropic, Google).
|
|
275
271
|
|
|
276
272
|
Returns:
|
|
277
|
-
List of tool definitions
|
|
273
|
+
List of tool definitions (OpenAI format by default).
|
|
278
274
|
|
|
279
275
|
Example:
|
|
280
276
|
>>> class ReadOnlyAgent(CrmAgentEnv):
|
|
@@ -285,7 +281,34 @@ IMPORTANT: Output ONLY a tool_call, no other text."""
|
|
|
285
281
|
... return [t for t in self._default_tools()
|
|
286
282
|
... if any(op in t['function']['name'] for op in read_ops)]
|
|
287
283
|
"""
|
|
288
|
-
return self._default_tools()
|
|
284
|
+
return self.format_tools(self._default_tools())
|
|
285
|
+
|
|
286
|
+
def format_tools(self, tools: list[JsonDict]) -> list[JsonDict]:
|
|
287
|
+
"""Format tool definitions for the target LLM provider.
|
|
288
|
+
|
|
289
|
+
Override this method to transform tool schemas for different providers.
|
|
290
|
+
The default implementation returns OpenAI-compatible format unchanged.
|
|
291
|
+
|
|
292
|
+
Args:
|
|
293
|
+
tools: List of tool definitions in OpenAI format.
|
|
294
|
+
|
|
295
|
+
Returns:
|
|
296
|
+
Formatted tool definitions for your target provider.
|
|
297
|
+
|
|
298
|
+
Example (Anthropic format):
|
|
299
|
+
>>> class AnthropicCrmAgent(CrmAgentEnv):
|
|
300
|
+
... def format_tools(self, tools):
|
|
301
|
+
... # Convert OpenAI format to Anthropic format
|
|
302
|
+
... return [
|
|
303
|
+
... {
|
|
304
|
+
... "name": t["function"]["name"],
|
|
305
|
+
... "description": t["function"]["description"],
|
|
306
|
+
... "input_schema": t["function"]["parameters"],
|
|
307
|
+
... }
|
|
308
|
+
... for t in tools
|
|
309
|
+
... ]
|
|
310
|
+
"""
|
|
311
|
+
return tools
|
|
289
312
|
|
|
290
313
|
def _default_tools(self) -> list[JsonDict]:
|
|
291
314
|
"""Return the default tool definitions.
|
|
@@ -293,548 +316,9 @@ IMPORTANT: Output ONLY a tool_call, no other text."""
|
|
|
293
316
|
Subclasses can call this to get all default tools and filter/extend them.
|
|
294
317
|
|
|
295
318
|
Returns:
|
|
296
|
-
Complete list of CRM tool definitions.
|
|
319
|
+
Complete list of CRM tool definitions in OpenAI format.
|
|
297
320
|
"""
|
|
298
|
-
return
|
|
299
|
-
# =================================================================
|
|
300
|
-
# Company Tools
|
|
301
|
-
# =================================================================
|
|
302
|
-
{
|
|
303
|
-
"type": "function",
|
|
304
|
-
"function": {
|
|
305
|
-
"name": "list_companies",
|
|
306
|
-
"description": "List all companies in the CRM",
|
|
307
|
-
"parameters": {
|
|
308
|
-
"type": "object",
|
|
309
|
-
"properties": {
|
|
310
|
-
"limit": {
|
|
311
|
-
"type": "integer",
|
|
312
|
-
"default": 60,
|
|
313
|
-
"description": "Maximum number of companies to return (max 200)",
|
|
314
|
-
},
|
|
315
|
-
"starting_after": {
|
|
316
|
-
"type": "string",
|
|
317
|
-
"description": "Cursor for pagination - returns objects after this ID",
|
|
318
|
-
},
|
|
319
|
-
"ending_before": {
|
|
320
|
-
"type": "string",
|
|
321
|
-
"description": "Cursor for pagination - returns objects before this ID",
|
|
322
|
-
},
|
|
323
|
-
"order_by": {
|
|
324
|
-
"type": "string",
|
|
325
|
-
"description": "Order by: field_name[ASC|DESC]",
|
|
326
|
-
},
|
|
327
|
-
"filter": {
|
|
328
|
-
"type": "string",
|
|
329
|
-
"description": "Filter: field[eq|gt|lt|contains]:value",
|
|
330
|
-
},
|
|
331
|
-
"depth": {
|
|
332
|
-
"type": "integer",
|
|
333
|
-
"default": 1,
|
|
334
|
-
"description": "Relation depth: 0=primary only, 1=include relations",
|
|
335
|
-
},
|
|
336
|
-
},
|
|
337
|
-
"required": [],
|
|
338
|
-
},
|
|
339
|
-
},
|
|
340
|
-
},
|
|
341
|
-
{
|
|
342
|
-
"type": "function",
|
|
343
|
-
"function": {
|
|
344
|
-
"name": "get_company",
|
|
345
|
-
"description": "Get details of a specific company",
|
|
346
|
-
"parameters": {
|
|
347
|
-
"type": "object",
|
|
348
|
-
"properties": {
|
|
349
|
-
"record_id": {
|
|
350
|
-
"type": "string",
|
|
351
|
-
"description": "ID of the company to retrieve",
|
|
352
|
-
},
|
|
353
|
-
"depth": {
|
|
354
|
-
"type": "integer",
|
|
355
|
-
"default": 1,
|
|
356
|
-
"description": "Relation depth: 0=primary only, 1=include relations",
|
|
357
|
-
},
|
|
358
|
-
},
|
|
359
|
-
"required": ["record_id"],
|
|
360
|
-
},
|
|
361
|
-
},
|
|
362
|
-
},
|
|
363
|
-
{
|
|
364
|
-
"type": "function",
|
|
365
|
-
"function": {
|
|
366
|
-
"name": "create_company",
|
|
367
|
-
"description": "Create a new company in the CRM",
|
|
368
|
-
"parameters": {
|
|
369
|
-
"type": "object",
|
|
370
|
-
"properties": {
|
|
371
|
-
"company_name": {
|
|
372
|
-
"type": "string",
|
|
373
|
-
"description": "Name of the company",
|
|
374
|
-
},
|
|
375
|
-
"company_domain": {
|
|
376
|
-
"type": "string",
|
|
377
|
-
"description": "Domain/website of the company",
|
|
378
|
-
},
|
|
379
|
-
"company_address": {
|
|
380
|
-
"type": "string",
|
|
381
|
-
"description": "Address of the company",
|
|
382
|
-
},
|
|
383
|
-
"company_employees": {
|
|
384
|
-
"type": "integer",
|
|
385
|
-
"description": "Number of employees",
|
|
386
|
-
},
|
|
387
|
-
},
|
|
388
|
-
"required": ["company_name"],
|
|
389
|
-
},
|
|
390
|
-
},
|
|
391
|
-
},
|
|
392
|
-
{
|
|
393
|
-
"type": "function",
|
|
394
|
-
"function": {
|
|
395
|
-
"name": "update_company",
|
|
396
|
-
"description": "Update an existing company",
|
|
397
|
-
"parameters": {
|
|
398
|
-
"type": "object",
|
|
399
|
-
"properties": {
|
|
400
|
-
"record_id": {
|
|
401
|
-
"type": "string",
|
|
402
|
-
"description": "ID of the company to update",
|
|
403
|
-
},
|
|
404
|
-
"company_name": {"type": "string"},
|
|
405
|
-
"company_domain": {"type": "string"},
|
|
406
|
-
"company_address": {"type": "string"},
|
|
407
|
-
"company_employees": {"type": "integer"},
|
|
408
|
-
},
|
|
409
|
-
"required": ["record_id"],
|
|
410
|
-
},
|
|
411
|
-
},
|
|
412
|
-
},
|
|
413
|
-
{
|
|
414
|
-
"type": "function",
|
|
415
|
-
"function": {
|
|
416
|
-
"name": "delete_company",
|
|
417
|
-
"description": "Delete a company from the CRM",
|
|
418
|
-
"parameters": {
|
|
419
|
-
"type": "object",
|
|
420
|
-
"properties": {
|
|
421
|
-
"record_id": {
|
|
422
|
-
"type": "string",
|
|
423
|
-
"description": "ID of the company to delete",
|
|
424
|
-
},
|
|
425
|
-
},
|
|
426
|
-
"required": ["record_id"],
|
|
427
|
-
},
|
|
428
|
-
},
|
|
429
|
-
},
|
|
430
|
-
# =================================================================
|
|
431
|
-
# Person/Contact Tools
|
|
432
|
-
# =================================================================
|
|
433
|
-
{
|
|
434
|
-
"type": "function",
|
|
435
|
-
"function": {
|
|
436
|
-
"name": "list_people",
|
|
437
|
-
"description": "List all contacts/people in the CRM",
|
|
438
|
-
"parameters": {
|
|
439
|
-
"type": "object",
|
|
440
|
-
"properties": {
|
|
441
|
-
"limit": {
|
|
442
|
-
"type": "integer",
|
|
443
|
-
"default": 60,
|
|
444
|
-
"description": "Maximum number of contacts to return (max 200)",
|
|
445
|
-
},
|
|
446
|
-
"starting_after": {"type": "string"},
|
|
447
|
-
"ending_before": {"type": "string"},
|
|
448
|
-
"order_by": {"type": "string"},
|
|
449
|
-
"filter": {"type": "string"},
|
|
450
|
-
"depth": {"type": "integer", "default": 1},
|
|
451
|
-
},
|
|
452
|
-
"required": [],
|
|
453
|
-
},
|
|
454
|
-
},
|
|
455
|
-
},
|
|
456
|
-
{
|
|
457
|
-
"type": "function",
|
|
458
|
-
"function": {
|
|
459
|
-
"name": "get_person",
|
|
460
|
-
"description": "Get details of a specific contact",
|
|
461
|
-
"parameters": {
|
|
462
|
-
"type": "object",
|
|
463
|
-
"properties": {
|
|
464
|
-
"record_id": {
|
|
465
|
-
"type": "string",
|
|
466
|
-
"description": "ID of the contact to retrieve",
|
|
467
|
-
},
|
|
468
|
-
"depth": {"type": "integer", "default": 1},
|
|
469
|
-
},
|
|
470
|
-
"required": ["record_id"],
|
|
471
|
-
},
|
|
472
|
-
},
|
|
473
|
-
},
|
|
474
|
-
{
|
|
475
|
-
"type": "function",
|
|
476
|
-
"function": {
|
|
477
|
-
"name": "create_person",
|
|
478
|
-
"description": "Create a new contact/person in the CRM",
|
|
479
|
-
"parameters": {
|
|
480
|
-
"type": "object",
|
|
481
|
-
"properties": {
|
|
482
|
-
"person_first_name": {
|
|
483
|
-
"type": "string",
|
|
484
|
-
"description": "First name",
|
|
485
|
-
},
|
|
486
|
-
"person_last_name": {
|
|
487
|
-
"type": "string",
|
|
488
|
-
"description": "Last name",
|
|
489
|
-
},
|
|
490
|
-
"person_email": {
|
|
491
|
-
"type": "string",
|
|
492
|
-
"description": "Email address",
|
|
493
|
-
},
|
|
494
|
-
"person_phone": {
|
|
495
|
-
"type": "string",
|
|
496
|
-
"description": "Phone number",
|
|
497
|
-
},
|
|
498
|
-
"person_company_id": {
|
|
499
|
-
"type": "string",
|
|
500
|
-
"description": "ID of associated company",
|
|
501
|
-
},
|
|
502
|
-
"person_job_title": {
|
|
503
|
-
"type": "string",
|
|
504
|
-
"description": "Job title",
|
|
505
|
-
},
|
|
506
|
-
},
|
|
507
|
-
"required": ["person_first_name", "person_last_name"],
|
|
508
|
-
},
|
|
509
|
-
},
|
|
510
|
-
},
|
|
511
|
-
{
|
|
512
|
-
"type": "function",
|
|
513
|
-
"function": {
|
|
514
|
-
"name": "update_person",
|
|
515
|
-
"description": "Update an existing contact",
|
|
516
|
-
"parameters": {
|
|
517
|
-
"type": "object",
|
|
518
|
-
"properties": {
|
|
519
|
-
"record_id": {
|
|
520
|
-
"type": "string",
|
|
521
|
-
"description": "ID of the contact to update",
|
|
522
|
-
},
|
|
523
|
-
"person_first_name": {"type": "string"},
|
|
524
|
-
"person_last_name": {"type": "string"},
|
|
525
|
-
"person_email": {"type": "string"},
|
|
526
|
-
"person_phone": {"type": "string"},
|
|
527
|
-
"person_job_title": {"type": "string"},
|
|
528
|
-
},
|
|
529
|
-
"required": ["record_id"],
|
|
530
|
-
},
|
|
531
|
-
},
|
|
532
|
-
},
|
|
533
|
-
{
|
|
534
|
-
"type": "function",
|
|
535
|
-
"function": {
|
|
536
|
-
"name": "delete_person",
|
|
537
|
-
"description": "Delete a contact from the CRM",
|
|
538
|
-
"parameters": {
|
|
539
|
-
"type": "object",
|
|
540
|
-
"properties": {
|
|
541
|
-
"record_id": {
|
|
542
|
-
"type": "string",
|
|
543
|
-
"description": "ID of the contact to delete",
|
|
544
|
-
},
|
|
545
|
-
},
|
|
546
|
-
"required": ["record_id"],
|
|
547
|
-
},
|
|
548
|
-
},
|
|
549
|
-
},
|
|
550
|
-
# =================================================================
|
|
551
|
-
# Opportunity Tools
|
|
552
|
-
# =================================================================
|
|
553
|
-
{
|
|
554
|
-
"type": "function",
|
|
555
|
-
"function": {
|
|
556
|
-
"name": "list_opportunities",
|
|
557
|
-
"description": "List all opportunities/deals in the CRM",
|
|
558
|
-
"parameters": {
|
|
559
|
-
"type": "object",
|
|
560
|
-
"properties": {
|
|
561
|
-
"limit": {
|
|
562
|
-
"type": "integer",
|
|
563
|
-
"default": 60,
|
|
564
|
-
"description": "Maximum number to return (max 200)",
|
|
565
|
-
},
|
|
566
|
-
"starting_after": {"type": "string"},
|
|
567
|
-
"ending_before": {"type": "string"},
|
|
568
|
-
"order_by": {"type": "string"},
|
|
569
|
-
"filter": {"type": "string"},
|
|
570
|
-
"depth": {"type": "integer", "default": 1},
|
|
571
|
-
},
|
|
572
|
-
"required": [],
|
|
573
|
-
},
|
|
574
|
-
},
|
|
575
|
-
},
|
|
576
|
-
{
|
|
577
|
-
"type": "function",
|
|
578
|
-
"function": {
|
|
579
|
-
"name": "get_opportunity",
|
|
580
|
-
"description": "Get details of a specific opportunity",
|
|
581
|
-
"parameters": {
|
|
582
|
-
"type": "object",
|
|
583
|
-
"properties": {
|
|
584
|
-
"record_id": {
|
|
585
|
-
"type": "string",
|
|
586
|
-
"description": "ID of the opportunity",
|
|
587
|
-
},
|
|
588
|
-
"depth": {"type": "integer", "default": 1},
|
|
589
|
-
},
|
|
590
|
-
"required": ["record_id"],
|
|
591
|
-
},
|
|
592
|
-
},
|
|
593
|
-
},
|
|
594
|
-
{
|
|
595
|
-
"type": "function",
|
|
596
|
-
"function": {
|
|
597
|
-
"name": "create_opportunity",
|
|
598
|
-
"description": "Create a new opportunity/deal",
|
|
599
|
-
"parameters": {
|
|
600
|
-
"type": "object",
|
|
601
|
-
"properties": {
|
|
602
|
-
"opportunity_name": {
|
|
603
|
-
"type": "string",
|
|
604
|
-
"description": "Name of the opportunity",
|
|
605
|
-
},
|
|
606
|
-
"opportunity_amount": {
|
|
607
|
-
"type": "number",
|
|
608
|
-
"description": "Deal value",
|
|
609
|
-
},
|
|
610
|
-
"opportunity_stage": {
|
|
611
|
-
"type": "string",
|
|
612
|
-
"enum": ["NEW", "MEETING", "PROPOSAL", "WON", "LOST"],
|
|
613
|
-
"description": "Sales stage",
|
|
614
|
-
},
|
|
615
|
-
"opportunity_close_date": {
|
|
616
|
-
"type": "string",
|
|
617
|
-
"description": "Expected close date (ISO format)",
|
|
618
|
-
},
|
|
619
|
-
"opportunity_company_id": {
|
|
620
|
-
"type": "string",
|
|
621
|
-
"description": "Associated company ID",
|
|
622
|
-
},
|
|
623
|
-
"opportunity_person_id": {
|
|
624
|
-
"type": "string",
|
|
625
|
-
"description": "Point of contact ID",
|
|
626
|
-
},
|
|
627
|
-
},
|
|
628
|
-
"required": ["opportunity_name"],
|
|
629
|
-
},
|
|
630
|
-
},
|
|
631
|
-
},
|
|
632
|
-
{
|
|
633
|
-
"type": "function",
|
|
634
|
-
"function": {
|
|
635
|
-
"name": "update_opportunity",
|
|
636
|
-
"description": "Update an existing opportunity",
|
|
637
|
-
"parameters": {
|
|
638
|
-
"type": "object",
|
|
639
|
-
"properties": {
|
|
640
|
-
"record_id": {
|
|
641
|
-
"type": "string",
|
|
642
|
-
"description": "ID of the opportunity to update",
|
|
643
|
-
},
|
|
644
|
-
"opportunity_name": {"type": "string"},
|
|
645
|
-
"opportunity_amount": {"type": "number"},
|
|
646
|
-
"opportunity_stage": {
|
|
647
|
-
"type": "string",
|
|
648
|
-
"enum": ["NEW", "MEETING", "PROPOSAL", "WON", "LOST"],
|
|
649
|
-
},
|
|
650
|
-
"opportunity_close_date": {"type": "string"},
|
|
651
|
-
},
|
|
652
|
-
"required": ["record_id"],
|
|
653
|
-
},
|
|
654
|
-
},
|
|
655
|
-
},
|
|
656
|
-
{
|
|
657
|
-
"type": "function",
|
|
658
|
-
"function": {
|
|
659
|
-
"name": "delete_opportunity",
|
|
660
|
-
"description": "Delete an opportunity",
|
|
661
|
-
"parameters": {
|
|
662
|
-
"type": "object",
|
|
663
|
-
"properties": {
|
|
664
|
-
"record_id": {
|
|
665
|
-
"type": "string",
|
|
666
|
-
"description": "ID of the opportunity to delete",
|
|
667
|
-
},
|
|
668
|
-
},
|
|
669
|
-
"required": ["record_id"],
|
|
670
|
-
},
|
|
671
|
-
},
|
|
672
|
-
},
|
|
673
|
-
# =================================================================
|
|
674
|
-
# Note Tools
|
|
675
|
-
# =================================================================
|
|
676
|
-
{
|
|
677
|
-
"type": "function",
|
|
678
|
-
"function": {
|
|
679
|
-
"name": "list_notes",
|
|
680
|
-
"description": "List all notes in the CRM",
|
|
681
|
-
"parameters": {
|
|
682
|
-
"type": "object",
|
|
683
|
-
"properties": {
|
|
684
|
-
"limit": {
|
|
685
|
-
"type": "integer",
|
|
686
|
-
"default": 10,
|
|
687
|
-
"description": "Maximum number of notes to return",
|
|
688
|
-
},
|
|
689
|
-
},
|
|
690
|
-
"required": [],
|
|
691
|
-
},
|
|
692
|
-
},
|
|
693
|
-
},
|
|
694
|
-
{
|
|
695
|
-
"type": "function",
|
|
696
|
-
"function": {
|
|
697
|
-
"name": "create_note",
|
|
698
|
-
"description": "Create a note attached to a record",
|
|
699
|
-
"parameters": {
|
|
700
|
-
"type": "object",
|
|
701
|
-
"properties": {
|
|
702
|
-
"note_body": {
|
|
703
|
-
"type": "string",
|
|
704
|
-
"description": "Content of the note",
|
|
705
|
-
},
|
|
706
|
-
"note_target_id": {
|
|
707
|
-
"type": "string",
|
|
708
|
-
"description": "ID of record to attach note to",
|
|
709
|
-
},
|
|
710
|
-
"note_target_type": {
|
|
711
|
-
"type": "string",
|
|
712
|
-
"enum": ["company", "person", "opportunity"],
|
|
713
|
-
"description": "Type of record",
|
|
714
|
-
},
|
|
715
|
-
},
|
|
716
|
-
"required": ["note_body"],
|
|
717
|
-
},
|
|
718
|
-
},
|
|
719
|
-
},
|
|
720
|
-
# =================================================================
|
|
721
|
-
# Task Tools
|
|
722
|
-
# =================================================================
|
|
723
|
-
{
|
|
724
|
-
"type": "function",
|
|
725
|
-
"function": {
|
|
726
|
-
"name": "list_tasks",
|
|
727
|
-
"description": "List all tasks in the CRM",
|
|
728
|
-
"parameters": {
|
|
729
|
-
"type": "object",
|
|
730
|
-
"properties": {
|
|
731
|
-
"limit": {
|
|
732
|
-
"type": "integer",
|
|
733
|
-
"default": 10,
|
|
734
|
-
"description": "Maximum number of tasks to return",
|
|
735
|
-
},
|
|
736
|
-
},
|
|
737
|
-
"required": [],
|
|
738
|
-
},
|
|
739
|
-
},
|
|
740
|
-
},
|
|
741
|
-
{
|
|
742
|
-
"type": "function",
|
|
743
|
-
"function": {
|
|
744
|
-
"name": "create_task",
|
|
745
|
-
"description": "Create a task, optionally linked to a record",
|
|
746
|
-
"parameters": {
|
|
747
|
-
"type": "object",
|
|
748
|
-
"properties": {
|
|
749
|
-
"task_title": {
|
|
750
|
-
"type": "string",
|
|
751
|
-
"description": "Title of the task",
|
|
752
|
-
},
|
|
753
|
-
"task_body": {
|
|
754
|
-
"type": "string",
|
|
755
|
-
"description": "Description",
|
|
756
|
-
},
|
|
757
|
-
"task_due_date": {
|
|
758
|
-
"type": "string",
|
|
759
|
-
"description": "Due date (ISO format)",
|
|
760
|
-
},
|
|
761
|
-
"task_status": {
|
|
762
|
-
"type": "string",
|
|
763
|
-
"enum": ["TODO", "IN_PROGRESS", "DONE"],
|
|
764
|
-
"description": "Status",
|
|
765
|
-
},
|
|
766
|
-
"task_target_id": {
|
|
767
|
-
"type": "string",
|
|
768
|
-
"description": "ID of record to link task to",
|
|
769
|
-
},
|
|
770
|
-
"task_target_type": {
|
|
771
|
-
"type": "string",
|
|
772
|
-
"enum": ["company", "person", "opportunity"],
|
|
773
|
-
"description": "Type of record",
|
|
774
|
-
},
|
|
775
|
-
},
|
|
776
|
-
"required": ["task_title"],
|
|
777
|
-
},
|
|
778
|
-
},
|
|
779
|
-
},
|
|
780
|
-
{
|
|
781
|
-
"type": "function",
|
|
782
|
-
"function": {
|
|
783
|
-
"name": "update_task",
|
|
784
|
-
"description": "Update an existing task",
|
|
785
|
-
"parameters": {
|
|
786
|
-
"type": "object",
|
|
787
|
-
"properties": {
|
|
788
|
-
"record_id": {
|
|
789
|
-
"type": "string",
|
|
790
|
-
"description": "ID of the task to update",
|
|
791
|
-
},
|
|
792
|
-
"task_title": {"type": "string"},
|
|
793
|
-
"task_body": {"type": "string"},
|
|
794
|
-
"task_due_date": {"type": "string"},
|
|
795
|
-
},
|
|
796
|
-
"required": ["record_id"],
|
|
797
|
-
},
|
|
798
|
-
},
|
|
799
|
-
},
|
|
800
|
-
{
|
|
801
|
-
"type": "function",
|
|
802
|
-
"function": {
|
|
803
|
-
"name": "complete_task",
|
|
804
|
-
"description": "Mark a task as complete",
|
|
805
|
-
"parameters": {
|
|
806
|
-
"type": "object",
|
|
807
|
-
"properties": {
|
|
808
|
-
"record_id": {
|
|
809
|
-
"type": "string",
|
|
810
|
-
"description": "ID of the task to complete",
|
|
811
|
-
},
|
|
812
|
-
},
|
|
813
|
-
"required": ["record_id"],
|
|
814
|
-
},
|
|
815
|
-
},
|
|
816
|
-
},
|
|
817
|
-
# =================================================================
|
|
818
|
-
# Submit Answer Tool
|
|
819
|
-
# =================================================================
|
|
820
|
-
{
|
|
821
|
-
"type": "function",
|
|
822
|
-
"function": {
|
|
823
|
-
"name": "submit_answer",
|
|
824
|
-
"description": "Submit final answer and end the session",
|
|
825
|
-
"parameters": {
|
|
826
|
-
"type": "object",
|
|
827
|
-
"properties": {
|
|
828
|
-
"answer": {
|
|
829
|
-
"type": "string",
|
|
830
|
-
"description": "The final answer based on CRM data",
|
|
831
|
-
},
|
|
832
|
-
},
|
|
833
|
-
"required": ["answer"],
|
|
834
|
-
},
|
|
835
|
-
},
|
|
836
|
-
},
|
|
837
|
-
]
|
|
321
|
+
return list(DEFAULT_TOOLS)
|
|
838
322
|
|
|
839
323
|
# =========================================================================
|
|
840
324
|
# Tool Parsing and Observation Formatting
|
|
@@ -967,6 +451,32 @@ IMPORTANT: Output ONLY a tool_call, no other text."""
|
|
|
967
451
|
if field in arguments and arguments[field] is not None:
|
|
968
452
|
action_kwargs[field] = arguments[field]
|
|
969
453
|
|
|
454
|
+
# Convert generic note_target_id/type to specific fields
|
|
455
|
+
# Tool schema uses: note_target_id + note_target_type
|
|
456
|
+
# Server expects: note_target_person_id, note_target_company_id, etc.
|
|
457
|
+
note_target_id = action_kwargs.pop("note_target_id", None)
|
|
458
|
+
note_target_type = action_kwargs.pop("note_target_type", None)
|
|
459
|
+
if note_target_id and note_target_type:
|
|
460
|
+
target_type = str(note_target_type).lower()
|
|
461
|
+
if target_type == "person":
|
|
462
|
+
action_kwargs["note_target_person_id"] = note_target_id
|
|
463
|
+
elif target_type == "company":
|
|
464
|
+
action_kwargs["note_target_company_id"] = note_target_id
|
|
465
|
+
elif target_type == "opportunity":
|
|
466
|
+
action_kwargs["note_target_opportunity_id"] = note_target_id
|
|
467
|
+
|
|
468
|
+
# Same conversion for tasks
|
|
469
|
+
task_target_id = action_kwargs.pop("task_target_id", None)
|
|
470
|
+
task_target_type = action_kwargs.pop("task_target_type", None)
|
|
471
|
+
if task_target_id and task_target_type:
|
|
472
|
+
target_type = str(task_target_type).lower()
|
|
473
|
+
if target_type == "person":
|
|
474
|
+
action_kwargs["task_target_person_id"] = task_target_id
|
|
475
|
+
elif target_type == "company":
|
|
476
|
+
action_kwargs["task_target_company_id"] = task_target_id
|
|
477
|
+
elif target_type == "opportunity":
|
|
478
|
+
action_kwargs["task_target_opportunity_id"] = task_target_id
|
|
479
|
+
|
|
970
480
|
try:
|
|
971
481
|
action = CrmAgentAction(**action_kwargs)
|
|
972
482
|
return ParsedAction(action=action, is_valid=True)
|