letta-client 1.0.0a9__py3-none-any.whl → 1.0.0a10__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.

Potentially problematic release.


This version of letta-client might be problematic. Click here for more details.

Files changed (45) hide show
  1. letta_client/_version.py +1 -1
  2. letta_client/resources/agents/agents.py +396 -396
  3. letta_client/resources/agents/blocks.py +200 -190
  4. letta_client/resources/agents/messages.py +367 -367
  5. letta_client/resources/archives.py +101 -101
  6. letta_client/resources/blocks/blocks.py +241 -222
  7. letta_client/resources/folders/folders.py +133 -133
  8. letta_client/resources/groups/groups.py +141 -141
  9. letta_client/resources/groups/messages.py +198 -198
  10. letta_client/resources/identities/blocks.py +7 -7
  11. letta_client/resources/identities/identities.py +141 -141
  12. letta_client/resources/tools.py +794 -194
  13. letta_client/types/__init__.py +11 -7
  14. letta_client/types/{agent_update_params.py → agent_modify_params.py} +2 -2
  15. letta_client/types/agent_state.py +6 -3
  16. letta_client/types/agents/__init__.py +6 -3
  17. letta_client/types/agents/block.py +6 -3
  18. letta_client/types/agents/block_list_response.py +63 -0
  19. letta_client/types/agents/{block_update_params.py → block_modify_params.py} +8 -5
  20. letta_client/types/agents/block_modify_response.py +63 -0
  21. letta_client/types/agents/block_retrieve_response.py +63 -0
  22. letta_client/types/agents/{message_update_params.py → message_modify_params.py} +2 -2
  23. letta_client/types/agents/{message_update_response.py → message_modify_response.py} +2 -2
  24. letta_client/types/{archive_update_params.py → archive_modify_params.py} +2 -2
  25. letta_client/types/block_create_params.py +6 -3
  26. letta_client/types/block_create_response.py +63 -0
  27. letta_client/types/block_list_response.py +63 -0
  28. letta_client/types/{block_update_params.py → block_modify_params.py} +8 -5
  29. letta_client/types/block_modify_response.py +63 -0
  30. letta_client/types/block_retrieve_response.py +63 -0
  31. letta_client/types/create_block_param.py +6 -3
  32. letta_client/types/{folder_update_params.py → folder_modify_params.py} +2 -2
  33. letta_client/types/{group_update_params.py → group_modify_params.py} +2 -2
  34. letta_client/types/groups/__init__.py +2 -2
  35. letta_client/types/groups/{message_update_params.py → message_modify_params.py} +2 -2
  36. letta_client/types/groups/{message_update_response.py → message_modify_response.py} +2 -2
  37. letta_client/types/identities/__init__.py +1 -0
  38. letta_client/types/identities/block_list_response.py +63 -0
  39. letta_client/types/{identity_update_params.py → identity_modify_params.py} +2 -2
  40. letta_client/types/tool.py +106 -2
  41. letta_client/types/{tool_update_params.py → tool_modify_params.py} +2 -2
  42. {letta_client-1.0.0a9.dist-info → letta_client-1.0.0a10.dist-info}/METADATA +1 -1
  43. {letta_client-1.0.0a9.dist-info → letta_client-1.0.0a10.dist-info}/RECORD +45 -37
  44. {letta_client-1.0.0a9.dist-info → letta_client-1.0.0a10.dist-info}/WHEEL +0 -0
  45. {letta_client-1.0.0a9.dist-info → letta_client-1.0.0a10.dist-info}/licenses/LICENSE +0 -0
@@ -7,7 +7,7 @@ from typing_extensions import Literal
7
7
 
8
8
  import httpx
9
9
 
10
- from ..types import tool_list_params, tool_count_params, tool_create_params, tool_update_params, tool_upsert_params
10
+ from ..types import tool_list_params, tool_count_params, tool_create_params, tool_modify_params, tool_upsert_params
11
11
  from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given
12
12
  from .._utils import maybe_transform, async_maybe_transform
13
13
  from .._compat import cached_property
@@ -19,12 +19,16 @@ from .._response import (
19
19
  async_to_streamed_response_wrapper,
20
20
  )
21
21
  from ..pagination import SyncArrayPage, AsyncArrayPage
22
- from ..types.tool import Tool
22
+ from ..types.tool import Tool, BaseTool
23
23
  from .._base_client import AsyncPaginator, make_request_options
24
24
  from ..types.tool_count_response import ToolCountResponse
25
25
  from ..types.npm_requirement_param import NpmRequirementParam
26
26
  from ..types.pip_requirement_param import PipRequirementParam
27
27
  from ..types.tool_upsert_base_tools_response import ToolUpsertBaseToolsResponse
28
+ import typing
29
+ from pydantic import BaseModel
30
+ from textwrap import dedent
31
+ import inspect
28
32
 
29
33
  __all__ = ["ToolsResource", "AsyncToolsResource"]
30
34
 
@@ -165,96 +169,6 @@ class ToolsResource(SyncAPIResource):
165
169
  cast_to=Tool,
166
170
  )
167
171
 
168
- def update(
169
- self,
170
- tool_id: str,
171
- *,
172
- args_json_schema: Optional[Dict[str, object]] | Omit = omit,
173
- default_requires_approval: Optional[bool] | Omit = omit,
174
- description: Optional[str] | Omit = omit,
175
- enable_parallel_execution: Optional[bool] | Omit = omit,
176
- json_schema: Optional[Dict[str, object]] | Omit = omit,
177
- metadata: Optional[Dict[str, object]] | Omit = omit,
178
- npm_requirements: Optional[Iterable[NpmRequirementParam]] | Omit = omit,
179
- pip_requirements: Optional[Iterable[PipRequirementParam]] | Omit = omit,
180
- return_char_limit: Optional[int] | Omit = omit,
181
- source_code: Optional[str] | Omit = omit,
182
- source_type: Optional[str] | Omit = omit,
183
- tags: Optional[SequenceNotStr[str]] | Omit = omit,
184
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
185
- # The extra values given here take precedence over values defined on the client or passed to this method.
186
- extra_headers: Headers | None = None,
187
- extra_query: Query | None = None,
188
- extra_body: Body | None = None,
189
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
190
- ) -> Tool:
191
- """
192
- Update an existing tool
193
-
194
- Args:
195
- tool_id: The ID of the tool in the format 'tool-<uuid4>'
196
-
197
- args_json_schema: The args JSON schema of the function.
198
-
199
- default_requires_approval: Whether or not to require approval before executing this tool.
200
-
201
- description: The description of the tool.
202
-
203
- enable_parallel_execution: If set to True, then this tool will potentially be executed concurrently with
204
- other tools. Default False.
205
-
206
- json_schema: The JSON schema of the function (auto-generated from source_code if not
207
- provided)
208
-
209
- metadata: A dictionary of additional metadata for the tool.
210
-
211
- npm_requirements: Optional list of npm packages required by this tool.
212
-
213
- pip_requirements: Optional list of pip packages required by this tool.
214
-
215
- return_char_limit: The maximum number of characters in the response.
216
-
217
- source_code: The source code of the function.
218
-
219
- source_type: The type of the source code.
220
-
221
- tags: Metadata tags.
222
-
223
- extra_headers: Send extra headers
224
-
225
- extra_query: Add additional query parameters to the request
226
-
227
- extra_body: Add additional JSON properties to the request
228
-
229
- timeout: Override the client-level default timeout for this request, in seconds
230
- """
231
- if not tool_id:
232
- raise ValueError(f"Expected a non-empty value for `tool_id` but received {tool_id!r}")
233
- return self._patch(
234
- f"/v1/tools/{tool_id}",
235
- body=maybe_transform(
236
- {
237
- "args_json_schema": args_json_schema,
238
- "default_requires_approval": default_requires_approval,
239
- "description": description,
240
- "enable_parallel_execution": enable_parallel_execution,
241
- "json_schema": json_schema,
242
- "metadata": metadata,
243
- "npm_requirements": npm_requirements,
244
- "pip_requirements": pip_requirements,
245
- "return_char_limit": return_char_limit,
246
- "source_code": source_code,
247
- "source_type": source_type,
248
- "tags": tags,
249
- },
250
- tool_update_params.ToolUpdateParams,
251
- ),
252
- options=make_request_options(
253
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
254
- ),
255
- cast_to=Tool,
256
- )
257
-
258
172
  def list(
259
173
  self,
260
174
  *,
@@ -448,6 +362,96 @@ class ToolsResource(SyncAPIResource):
448
362
  cast_to=int,
449
363
  )
450
364
 
365
+ def modify(
366
+ self,
367
+ tool_id: str,
368
+ *,
369
+ args_json_schema: Optional[Dict[str, object]] | Omit = omit,
370
+ default_requires_approval: Optional[bool] | Omit = omit,
371
+ description: Optional[str] | Omit = omit,
372
+ enable_parallel_execution: Optional[bool] | Omit = omit,
373
+ json_schema: Optional[Dict[str, object]] | Omit = omit,
374
+ metadata: Optional[Dict[str, object]] | Omit = omit,
375
+ npm_requirements: Optional[Iterable[NpmRequirementParam]] | Omit = omit,
376
+ pip_requirements: Optional[Iterable[PipRequirementParam]] | Omit = omit,
377
+ return_char_limit: Optional[int] | Omit = omit,
378
+ source_code: Optional[str] | Omit = omit,
379
+ source_type: Optional[str] | Omit = omit,
380
+ tags: Optional[SequenceNotStr[str]] | Omit = omit,
381
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
382
+ # The extra values given here take precedence over values defined on the client or passed to this method.
383
+ extra_headers: Headers | None = None,
384
+ extra_query: Query | None = None,
385
+ extra_body: Body | None = None,
386
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
387
+ ) -> Tool:
388
+ """
389
+ Update an existing tool
390
+
391
+ Args:
392
+ tool_id: The ID of the tool in the format 'tool-<uuid4>'
393
+
394
+ args_json_schema: The args JSON schema of the function.
395
+
396
+ default_requires_approval: Whether or not to require approval before executing this tool.
397
+
398
+ description: The description of the tool.
399
+
400
+ enable_parallel_execution: If set to True, then this tool will potentially be executed concurrently with
401
+ other tools. Default False.
402
+
403
+ json_schema: The JSON schema of the function (auto-generated from source_code if not
404
+ provided)
405
+
406
+ metadata: A dictionary of additional metadata for the tool.
407
+
408
+ npm_requirements: Optional list of npm packages required by this tool.
409
+
410
+ pip_requirements: Optional list of pip packages required by this tool.
411
+
412
+ return_char_limit: The maximum number of characters in the response.
413
+
414
+ source_code: The source code of the function.
415
+
416
+ source_type: The type of the source code.
417
+
418
+ tags: Metadata tags.
419
+
420
+ extra_headers: Send extra headers
421
+
422
+ extra_query: Add additional query parameters to the request
423
+
424
+ extra_body: Add additional JSON properties to the request
425
+
426
+ timeout: Override the client-level default timeout for this request, in seconds
427
+ """
428
+ if not tool_id:
429
+ raise ValueError(f"Expected a non-empty value for `tool_id` but received {tool_id!r}")
430
+ return self._patch(
431
+ f"/v1/tools/{tool_id}",
432
+ body=maybe_transform(
433
+ {
434
+ "args_json_schema": args_json_schema,
435
+ "default_requires_approval": default_requires_approval,
436
+ "description": description,
437
+ "enable_parallel_execution": enable_parallel_execution,
438
+ "json_schema": json_schema,
439
+ "metadata": metadata,
440
+ "npm_requirements": npm_requirements,
441
+ "pip_requirements": pip_requirements,
442
+ "return_char_limit": return_char_limit,
443
+ "source_code": source_code,
444
+ "source_type": source_type,
445
+ "tags": tags,
446
+ },
447
+ tool_modify_params.ToolModifyParams,
448
+ ),
449
+ options=make_request_options(
450
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
451
+ ),
452
+ cast_to=Tool,
453
+ )
454
+
451
455
  def upsert(
452
456
  self,
453
457
  *,
@@ -548,6 +552,303 @@ class ToolsResource(SyncAPIResource):
548
552
  cast_to=ToolUpsertBaseToolsResponse,
549
553
  )
550
554
 
555
+ def create_from_function(
556
+ self,
557
+ *,
558
+ func: typing.Callable[..., typing.Any],
559
+ args_schema: typing.Optional[typing.Type[BaseModel]] | Omit = omit,
560
+ description: Optional[str] | Omit = omit,
561
+ tags: Optional[SequenceNotStr[str]] | Omit = omit,
562
+ source_type: str | Omit = omit,
563
+ json_schema: Optional[Dict[str, object]] | Omit = omit,
564
+ return_char_limit: int | Omit = omit,
565
+ pip_requirements: Optional[Iterable[PipRequirementParam]] | Omit = omit,
566
+ npm_requirements: Optional[Iterable[NpmRequirementParam]] | Omit = omit,
567
+ default_requires_approval: Optional[bool] | Omit = omit,
568
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
569
+ # The extra values given here take precedence over values defined on the client or passed to this method.
570
+ extra_headers: Headers | None = None,
571
+ extra_query: Query | None = None,
572
+ extra_body: Body | None = None,
573
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
574
+ ) -> Tool:
575
+ """
576
+ Create a new tool from a callable
577
+
578
+ Args:
579
+ func: The callable to create the tool from.
580
+
581
+ args_schema: The arguments schema of the function, as a Pydantic model.
582
+
583
+ description: The description of the tool.
584
+
585
+ tags: Metadata tags.
586
+
587
+ source_type: The source type of the function.
588
+
589
+ json_schema: The JSON schema of the function (auto-generated from source_code if not
590
+ provided)
591
+
592
+ return_char_limit: The maximum number of characters in the response.
593
+
594
+ pip_requirements: Optional list of pip packages required by this tool.
595
+
596
+ npm_requirements: Optional list of npm packages required by this tool.
597
+
598
+ default_requires_approval: Whether or not to require approval before executing this tool.
599
+
600
+ extra_headers: Send extra headers
601
+
602
+ extra_query: Add additional query parameters to the request
603
+
604
+ extra_body: Add additional JSON properties to the request
605
+
606
+ timeout: Override the client-level default timeout for this request, in seconds
607
+
608
+ Examples:
609
+ from letta_client import Letta
610
+
611
+ client = Letta(
612
+ token="YOUR_TOKEN",
613
+ )
614
+
615
+ def add_two_numbers(a: int, b: int) -> int:
616
+ return a + b
617
+
618
+ client.tools.create_from_function(
619
+ func=add_two_numbers,
620
+ )
621
+
622
+ class InventoryEntryData(BaseModel):
623
+ data: InventoryEntry
624
+ quantity_change: int
625
+
626
+ def manage_inventory(data: InventoryEntry, quantity_change: int) -> bool:
627
+ pass
628
+
629
+ client.tools.create_from_function(
630
+ func=manage_inventory,
631
+ args_schema=InventoryEntryData,
632
+ )
633
+ """
634
+ source_code = dedent(inspect.getsource(func))
635
+ args_json_schema: Optional[Dict[str, object]] | Omit = omit
636
+ if not isinstance(args_schema, Omit) and args_schema is not None:
637
+ args_json_schema = args_schema.model_json_schema()
638
+
639
+ return self.create(
640
+ source_code=source_code,
641
+ args_json_schema=args_json_schema,
642
+ description=description,
643
+ tags=tags,
644
+ source_type=source_type,
645
+ json_schema=json_schema,
646
+ return_char_limit=return_char_limit,
647
+ pip_requirements=pip_requirements,
648
+ npm_requirements=npm_requirements,
649
+ default_requires_approval=default_requires_approval,
650
+ extra_headers=extra_headers,
651
+ extra_query=extra_query,
652
+ extra_body=extra_body,
653
+ timeout=timeout,
654
+ )
655
+
656
+ def upsert_from_function(
657
+ self,
658
+ *,
659
+ func: typing.Callable[..., typing.Any],
660
+ args_schema: typing.Optional[typing.Type[BaseModel]] | Omit = omit,
661
+ description: Optional[str] | Omit = omit,
662
+ tags: Optional[SequenceNotStr[str]] | Omit = omit,
663
+ source_type: str | Omit = omit,
664
+ json_schema: Optional[Dict[str, object]] | Omit = omit,
665
+ return_char_limit: int | Omit = omit,
666
+ pip_requirements: Optional[Iterable[PipRequirementParam]] | Omit = omit,
667
+ npm_requirements: Optional[Iterable[NpmRequirementParam]] | Omit = omit,
668
+ default_requires_approval: Optional[bool] | Omit = omit,
669
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
670
+ # The extra values given here take precedence over values defined on the client or passed to this method.
671
+ extra_headers: Headers | None = None,
672
+ extra_query: Query | None = None,
673
+ extra_body: Body | None = None,
674
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
675
+ ) -> Tool:
676
+ """
677
+ Create or update a tool from a callable
678
+
679
+ Args:
680
+ func: The callable to create or update the tool from.
681
+
682
+ args_schema: The arguments schema of the function, as a Pydantic model.
683
+
684
+ description: The description of the tool.
685
+
686
+ tags: Metadata tags.
687
+
688
+ source_type: The source type of the function.
689
+
690
+ json_schema: The JSON schema of the function (auto-generated from source_code if not
691
+ provided)
692
+
693
+ return_char_limit: The maximum number of characters in the response.
694
+
695
+ pip_requirements: Optional list of pip packages required by this tool.
696
+
697
+ npm_requirements: Optional list of npm packages required by this tool.
698
+
699
+ default_requires_approval: Whether or not to require approval before executing this tool.
700
+
701
+ extra_headers: Send extra headers
702
+
703
+ extra_query: Add additional query parameters to the request
704
+
705
+ extra_body: Add additional JSON properties to the request
706
+
707
+ timeout: Override the client-level default timeout for this request, in seconds
708
+
709
+ Examples:
710
+ from letta_client import Letta
711
+
712
+ client = Letta(
713
+ token="YOUR_TOKEN",
714
+ )
715
+
716
+ def add_two_numbers(a: int, b: int) -> int:
717
+ return a + b
718
+
719
+ client.tools.upsert_from_function(
720
+ func=add_two_numbers,
721
+ )
722
+
723
+ class InventoryEntryData(BaseModel):
724
+ data: InventoryEntry
725
+ quantity_change: int
726
+
727
+ def manage_inventory(data: InventoryEntry, quantity_change: int) -> bool:
728
+ pass
729
+
730
+ client.tools.upsert_from_function(
731
+ func=manage_inventory,
732
+ args_schema=InventoryEntryData,
733
+ )
734
+ """
735
+ source_code = dedent(inspect.getsource(func))
736
+ args_json_schema: Optional[Dict[str, object]] | Omit = omit
737
+ if not isinstance(args_schema, Omit) and args_schema is not None:
738
+ args_json_schema = args_schema.model_json_schema()
739
+
740
+ return self.upsert(
741
+ source_code=source_code,
742
+ args_json_schema=args_json_schema,
743
+ description=description,
744
+ tags=tags,
745
+ source_type=source_type,
746
+ json_schema=json_schema,
747
+ return_char_limit=return_char_limit,
748
+ pip_requirements=pip_requirements,
749
+ npm_requirements=npm_requirements,
750
+ default_requires_approval=default_requires_approval,
751
+ extra_headers=extra_headers,
752
+ extra_query=extra_query,
753
+ extra_body=extra_body,
754
+ timeout=timeout,
755
+ )
756
+
757
+ def add(
758
+ self,
759
+ *,
760
+ tool: BaseTool,
761
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
762
+ # The extra values given here take precedence over values defined on the client or passed to this method.
763
+ extra_headers: Headers | None = None,
764
+ extra_query: Query | None = None,
765
+ extra_body: Body | None = None,
766
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
767
+ ) -> Tool:
768
+ """
769
+ Add a tool to Letta from a custom Tool class
770
+
771
+ Args:
772
+ tool: The tool object to be added.
773
+
774
+ extra_headers: Send extra headers
775
+
776
+ extra_query: Add additional query parameters to the request
777
+
778
+ extra_body: Add additional JSON properties to the request
779
+
780
+ timeout: Override the client-level default timeout for this request, in seconds
781
+
782
+ Examples:
783
+ from letta_client import Letta
784
+
785
+ client = Letta(
786
+ token="YOUR_TOKEN",
787
+ )
788
+
789
+ class InventoryItem(BaseModel):
790
+ sku: str # Unique product identifier
791
+ name: str # Product name
792
+ price: float # Current price
793
+ category: str # Product category (e.g., "Electronics", "Clothing")
794
+
795
+ class InventoryEntry(BaseModel):
796
+ timestamp: int # Unix timestamp of the transaction
797
+ item: InventoryItem # The product being updated
798
+ transaction_id: str # Unique identifier for this inventory update
799
+
800
+ class InventoryEntryData(BaseModel):
801
+ data: InventoryEntry
802
+ quantity_change: int # Change in quantity (positive for additions, negative for removals)
803
+
804
+ class ManageInventoryTool(BaseTool):
805
+ name: str = "manage_inventory"
806
+ args_schema: Type[BaseModel] = InventoryEntryData
807
+ description: str = "Update inventory catalogue with a new data entry"
808
+ tags: List[str] = ["inventory", "shop"]
809
+
810
+ def run(self, data: InventoryEntry, quantity_change: int) -> bool:
811
+ '''
812
+ Implementation of the manage_inventory tool
813
+ '''
814
+ print(f"Updated inventory for {data.item.name} with a quantity change of {quantity_change}")
815
+ return True
816
+
817
+ client.tools.add(
818
+ tool=ManageInventoryTool()
819
+ )
820
+ """
821
+ source_code = tool.get_source_code()
822
+ args_json_schema = tool.args_schema.model_json_schema() if tool.args_schema else None
823
+
824
+ # Convert PipRequirement/NpmRequirement models to Param dicts
825
+ pip_requirements_param = (
826
+ [typing.cast(PipRequirementParam, req.model_dump()) for req in tool.pip_requirements]
827
+ if tool.pip_requirements
828
+ else omit
829
+ )
830
+ npm_requirements_param = (
831
+ [typing.cast(NpmRequirementParam, req.model_dump()) for req in tool.npm_requirements]
832
+ if tool.npm_requirements
833
+ else omit
834
+ )
835
+
836
+ return self.upsert(
837
+ source_code=source_code,
838
+ args_json_schema=args_json_schema or omit,
839
+ description=tool.description or omit,
840
+ tags=tool.tags or omit,
841
+ source_type=tool.source_type or omit,
842
+ json_schema=tool.json_schema or omit,
843
+ return_char_limit=tool.return_char_limit or omit,
844
+ pip_requirements=pip_requirements_param,
845
+ npm_requirements=npm_requirements_param,
846
+ default_requires_approval=tool.default_requires_approval or omit,
847
+ extra_headers=extra_headers,
848
+ extra_query=extra_query,
849
+ extra_body=extra_body,
850
+ timeout=timeout,
851
+ )
551
852
 
552
853
  class AsyncToolsResource(AsyncAPIResource):
553
854
  @cached_property
@@ -685,96 +986,6 @@ class AsyncToolsResource(AsyncAPIResource):
685
986
  cast_to=Tool,
686
987
  )
687
988
 
688
- async def update(
689
- self,
690
- tool_id: str,
691
- *,
692
- args_json_schema: Optional[Dict[str, object]] | Omit = omit,
693
- default_requires_approval: Optional[bool] | Omit = omit,
694
- description: Optional[str] | Omit = omit,
695
- enable_parallel_execution: Optional[bool] | Omit = omit,
696
- json_schema: Optional[Dict[str, object]] | Omit = omit,
697
- metadata: Optional[Dict[str, object]] | Omit = omit,
698
- npm_requirements: Optional[Iterable[NpmRequirementParam]] | Omit = omit,
699
- pip_requirements: Optional[Iterable[PipRequirementParam]] | Omit = omit,
700
- return_char_limit: Optional[int] | Omit = omit,
701
- source_code: Optional[str] | Omit = omit,
702
- source_type: Optional[str] | Omit = omit,
703
- tags: Optional[SequenceNotStr[str]] | Omit = omit,
704
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
705
- # The extra values given here take precedence over values defined on the client or passed to this method.
706
- extra_headers: Headers | None = None,
707
- extra_query: Query | None = None,
708
- extra_body: Body | None = None,
709
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
710
- ) -> Tool:
711
- """
712
- Update an existing tool
713
-
714
- Args:
715
- tool_id: The ID of the tool in the format 'tool-<uuid4>'
716
-
717
- args_json_schema: The args JSON schema of the function.
718
-
719
- default_requires_approval: Whether or not to require approval before executing this tool.
720
-
721
- description: The description of the tool.
722
-
723
- enable_parallel_execution: If set to True, then this tool will potentially be executed concurrently with
724
- other tools. Default False.
725
-
726
- json_schema: The JSON schema of the function (auto-generated from source_code if not
727
- provided)
728
-
729
- metadata: A dictionary of additional metadata for the tool.
730
-
731
- npm_requirements: Optional list of npm packages required by this tool.
732
-
733
- pip_requirements: Optional list of pip packages required by this tool.
734
-
735
- return_char_limit: The maximum number of characters in the response.
736
-
737
- source_code: The source code of the function.
738
-
739
- source_type: The type of the source code.
740
-
741
- tags: Metadata tags.
742
-
743
- extra_headers: Send extra headers
744
-
745
- extra_query: Add additional query parameters to the request
746
-
747
- extra_body: Add additional JSON properties to the request
748
-
749
- timeout: Override the client-level default timeout for this request, in seconds
750
- """
751
- if not tool_id:
752
- raise ValueError(f"Expected a non-empty value for `tool_id` but received {tool_id!r}")
753
- return await self._patch(
754
- f"/v1/tools/{tool_id}",
755
- body=await async_maybe_transform(
756
- {
757
- "args_json_schema": args_json_schema,
758
- "default_requires_approval": default_requires_approval,
759
- "description": description,
760
- "enable_parallel_execution": enable_parallel_execution,
761
- "json_schema": json_schema,
762
- "metadata": metadata,
763
- "npm_requirements": npm_requirements,
764
- "pip_requirements": pip_requirements,
765
- "return_char_limit": return_char_limit,
766
- "source_code": source_code,
767
- "source_type": source_type,
768
- "tags": tags,
769
- },
770
- tool_update_params.ToolUpdateParams,
771
- ),
772
- options=make_request_options(
773
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
774
- ),
775
- cast_to=Tool,
776
- )
777
-
778
989
  def list(
779
990
  self,
780
991
  *,
@@ -968,6 +1179,96 @@ class AsyncToolsResource(AsyncAPIResource):
968
1179
  cast_to=int,
969
1180
  )
970
1181
 
1182
+ async def modify(
1183
+ self,
1184
+ tool_id: str,
1185
+ *,
1186
+ args_json_schema: Optional[Dict[str, object]] | Omit = omit,
1187
+ default_requires_approval: Optional[bool] | Omit = omit,
1188
+ description: Optional[str] | Omit = omit,
1189
+ enable_parallel_execution: Optional[bool] | Omit = omit,
1190
+ json_schema: Optional[Dict[str, object]] | Omit = omit,
1191
+ metadata: Optional[Dict[str, object]] | Omit = omit,
1192
+ npm_requirements: Optional[Iterable[NpmRequirementParam]] | Omit = omit,
1193
+ pip_requirements: Optional[Iterable[PipRequirementParam]] | Omit = omit,
1194
+ return_char_limit: Optional[int] | Omit = omit,
1195
+ source_code: Optional[str] | Omit = omit,
1196
+ source_type: Optional[str] | Omit = omit,
1197
+ tags: Optional[SequenceNotStr[str]] | Omit = omit,
1198
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
1199
+ # The extra values given here take precedence over values defined on the client or passed to this method.
1200
+ extra_headers: Headers | None = None,
1201
+ extra_query: Query | None = None,
1202
+ extra_body: Body | None = None,
1203
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
1204
+ ) -> Tool:
1205
+ """
1206
+ Update an existing tool
1207
+
1208
+ Args:
1209
+ tool_id: The ID of the tool in the format 'tool-<uuid4>'
1210
+
1211
+ args_json_schema: The args JSON schema of the function.
1212
+
1213
+ default_requires_approval: Whether or not to require approval before executing this tool.
1214
+
1215
+ description: The description of the tool.
1216
+
1217
+ enable_parallel_execution: If set to True, then this tool will potentially be executed concurrently with
1218
+ other tools. Default False.
1219
+
1220
+ json_schema: The JSON schema of the function (auto-generated from source_code if not
1221
+ provided)
1222
+
1223
+ metadata: A dictionary of additional metadata for the tool.
1224
+
1225
+ npm_requirements: Optional list of npm packages required by this tool.
1226
+
1227
+ pip_requirements: Optional list of pip packages required by this tool.
1228
+
1229
+ return_char_limit: The maximum number of characters in the response.
1230
+
1231
+ source_code: The source code of the function.
1232
+
1233
+ source_type: The type of the source code.
1234
+
1235
+ tags: Metadata tags.
1236
+
1237
+ extra_headers: Send extra headers
1238
+
1239
+ extra_query: Add additional query parameters to the request
1240
+
1241
+ extra_body: Add additional JSON properties to the request
1242
+
1243
+ timeout: Override the client-level default timeout for this request, in seconds
1244
+ """
1245
+ if not tool_id:
1246
+ raise ValueError(f"Expected a non-empty value for `tool_id` but received {tool_id!r}")
1247
+ return await self._patch(
1248
+ f"/v1/tools/{tool_id}",
1249
+ body=await async_maybe_transform(
1250
+ {
1251
+ "args_json_schema": args_json_schema,
1252
+ "default_requires_approval": default_requires_approval,
1253
+ "description": description,
1254
+ "enable_parallel_execution": enable_parallel_execution,
1255
+ "json_schema": json_schema,
1256
+ "metadata": metadata,
1257
+ "npm_requirements": npm_requirements,
1258
+ "pip_requirements": pip_requirements,
1259
+ "return_char_limit": return_char_limit,
1260
+ "source_code": source_code,
1261
+ "source_type": source_type,
1262
+ "tags": tags,
1263
+ },
1264
+ tool_modify_params.ToolModifyParams,
1265
+ ),
1266
+ options=make_request_options(
1267
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
1268
+ ),
1269
+ cast_to=Tool,
1270
+ )
1271
+
971
1272
  async def upsert(
972
1273
  self,
973
1274
  *,
@@ -1068,6 +1369,305 @@ class AsyncToolsResource(AsyncAPIResource):
1068
1369
  cast_to=ToolUpsertBaseToolsResponse,
1069
1370
  )
1070
1371
 
1372
+ async def create_from_function(
1373
+ self,
1374
+ *,
1375
+ func: typing.Callable[..., typing.Any],
1376
+ args_schema: typing.Optional[typing.Type[BaseModel]] | Omit = omit,
1377
+ description: Optional[str] | Omit = omit,
1378
+ tags: Optional[SequenceNotStr[str]] | Omit = omit,
1379
+ source_type: str | Omit = omit,
1380
+ json_schema: Optional[Dict[str, object]] | Omit = omit,
1381
+ return_char_limit: int | Omit = omit,
1382
+ pip_requirements: Optional[Iterable[PipRequirementParam]] | Omit = omit,
1383
+ npm_requirements: Optional[Iterable[NpmRequirementParam]] | Omit = omit,
1384
+ default_requires_approval: Optional[bool] | Omit = omit,
1385
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
1386
+ # The extra values given here take precedence over values defined on the client or passed to this method.
1387
+ extra_headers: Headers | None = None,
1388
+ extra_query: Query | None = None,
1389
+ extra_body: Body | None = None,
1390
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
1391
+ ) -> Tool:
1392
+ """
1393
+ Create a new tool from a callable
1394
+
1395
+ Args:
1396
+ func: The callable to create the tool from.
1397
+
1398
+ args_schema: The arguments schema of the function, as a Pydantic model.
1399
+
1400
+ description: The description of the tool.
1401
+
1402
+ tags: Metadata tags.
1403
+
1404
+ source_type: The source type of the function.
1405
+
1406
+ json_schema: The JSON schema of the function (auto-generated from source_code if not
1407
+ provided)
1408
+
1409
+ return_char_limit: The maximum number of characters in the response.
1410
+
1411
+ pip_requirements: Optional list of pip packages required by this tool.
1412
+
1413
+ npm_requirements: Optional list of npm packages required by this tool.
1414
+
1415
+ default_requires_approval: Whether or not to require approval before executing this tool.
1416
+
1417
+ extra_headers: Send extra headers
1418
+
1419
+ extra_query: Add additional query parameters to the request
1420
+
1421
+ extra_body: Add additional JSON properties to the request
1422
+
1423
+ timeout: Override the client-level default timeout for this request, in seconds
1424
+
1425
+ Examples:
1426
+ from letta_client import Letta
1427
+
1428
+ client = Letta(
1429
+ token="YOUR_TOKEN",
1430
+ )
1431
+
1432
+ def add_two_numbers(a: int, b: int) -> int:
1433
+ return a + b
1434
+
1435
+ await client.tools.create_from_function(
1436
+ func=add_two_numbers,
1437
+ )
1438
+
1439
+ class InventoryEntryData(BaseModel):
1440
+ data: InventoryEntry
1441
+ quantity_change: int
1442
+
1443
+ def manage_inventory(data: InventoryEntry, quantity_change: int) -> bool:
1444
+ pass
1445
+
1446
+ await client.tools.create_from_function(
1447
+ func=manage_inventory,
1448
+ args_schema=InventoryEntryData,
1449
+ )
1450
+ """
1451
+ source_code = dedent(inspect.getsource(func))
1452
+ args_json_schema: Optional[Dict[str, object]] | Omit = omit
1453
+ if not isinstance(args_schema, Omit) and args_schema is not None:
1454
+ args_json_schema = args_schema.model_json_schema()
1455
+
1456
+ return await self.create(
1457
+ source_code=source_code,
1458
+ args_json_schema=args_json_schema,
1459
+ description=description,
1460
+ tags=tags,
1461
+ source_type=source_type,
1462
+ json_schema=json_schema,
1463
+ return_char_limit=return_char_limit,
1464
+ pip_requirements=pip_requirements,
1465
+ npm_requirements=npm_requirements,
1466
+ default_requires_approval=default_requires_approval,
1467
+ extra_headers=extra_headers,
1468
+ extra_query=extra_query,
1469
+ extra_body=extra_body,
1470
+ timeout=timeout,
1471
+ )
1472
+
1473
+
1474
+ async def upsert_from_function(
1475
+ self,
1476
+ *,
1477
+ func: typing.Callable[..., typing.Any],
1478
+ args_schema: typing.Optional[typing.Type[BaseModel]] | Omit = omit,
1479
+ description: Optional[str] | Omit = omit,
1480
+ tags: Optional[SequenceNotStr[str]] | Omit = omit,
1481
+ source_type: str | Omit = omit,
1482
+ json_schema: Optional[Dict[str, object]] | Omit = omit,
1483
+ return_char_limit: int | Omit = omit,
1484
+ pip_requirements: Optional[Iterable[PipRequirementParam]] | Omit = omit,
1485
+ npm_requirements: Optional[Iterable[NpmRequirementParam]] | Omit = omit,
1486
+ default_requires_approval: Optional[bool] | Omit = omit,
1487
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
1488
+ # The extra values given here take precedence over values defined on the client or passed to this method.
1489
+ extra_headers: Headers | None = None,
1490
+ extra_query: Query | None = None,
1491
+ extra_body: Body | None = None,
1492
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
1493
+ ) -> Tool:
1494
+ """
1495
+ Create or update a tool from a callable
1496
+
1497
+ Args:
1498
+ func: The callable to create or update the tool from.
1499
+
1500
+ args_schema: The arguments schema of the function, as a Pydantic model.
1501
+
1502
+ description: The description of the tool.
1503
+
1504
+ tags: Metadata tags.
1505
+
1506
+ source_type: The source type of the function.
1507
+
1508
+ json_schema: The JSON schema of the function (auto-generated from source_code if not
1509
+ provided)
1510
+
1511
+ return_char_limit: The maximum number of characters in the response.
1512
+
1513
+ pip_requirements: Optional list of pip packages required by this tool.
1514
+
1515
+ npm_requirements: Optional list of npm packages required by this tool.
1516
+
1517
+ default_requires_approval: Whether or not to require approval before executing this tool.
1518
+
1519
+ extra_headers: Send extra headers
1520
+
1521
+ extra_query: Add additional query parameters to the request
1522
+
1523
+ extra_body: Add additional JSON properties to the request
1524
+
1525
+ timeout: Override the client-level default timeout for this request, in seconds
1526
+
1527
+ Examples:
1528
+ from letta_client import Letta
1529
+
1530
+ client = Letta(
1531
+ token="YOUR_TOKEN",
1532
+ )
1533
+
1534
+ def add_two_numbers(a: int, b: int) -> int:
1535
+ return a + b
1536
+
1537
+ await client.tools.upsert_from_function(
1538
+ func=add_two_numbers,
1539
+ )
1540
+
1541
+ class InventoryEntryData(BaseModel):
1542
+ data: InventoryEntry
1543
+ quantity_change: int
1544
+
1545
+ def manage_inventory(data: InventoryEntry, quantity_change: int) -> bool:
1546
+ pass
1547
+
1548
+ await client.tools.upsert_from_function(
1549
+ func=manage_inventory,
1550
+ args_schema=InventoryEntryData,
1551
+ )
1552
+ """
1553
+ source_code = dedent(inspect.getsource(func))
1554
+ args_json_schema: Optional[Dict[str, object]] | Omit = omit
1555
+ if not isinstance(args_schema, Omit) and args_schema is not None:
1556
+ args_json_schema = args_schema.model_json_schema()
1557
+
1558
+ return await self.upsert(
1559
+ source_code=source_code,
1560
+ args_json_schema=args_json_schema,
1561
+ description=description,
1562
+ tags=tags,
1563
+ source_type=source_type,
1564
+ json_schema=json_schema,
1565
+ return_char_limit=return_char_limit,
1566
+ pip_requirements=pip_requirements,
1567
+ npm_requirements=npm_requirements,
1568
+ default_requires_approval=default_requires_approval,
1569
+ extra_headers=extra_headers,
1570
+ extra_query=extra_query,
1571
+ extra_body=extra_body,
1572
+ timeout=timeout,
1573
+ )
1574
+
1575
+ async def add(
1576
+ self,
1577
+ *,
1578
+ tool: BaseTool,
1579
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
1580
+ # The extra values given here take precedence over values defined on the client or passed to this method.
1581
+ extra_headers: Headers | None = None,
1582
+ extra_query: Query | None = None,
1583
+ extra_body: Body | None = None,
1584
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
1585
+ ) -> Tool:
1586
+ """
1587
+ Add a tool to Letta from a custom Tool class
1588
+
1589
+ Args:
1590
+ tool: The tool object to be added.
1591
+
1592
+ extra_headers: Send extra headers
1593
+
1594
+ extra_query: Add additional query parameters to the request
1595
+
1596
+ extra_body: Add additional JSON properties to the request
1597
+
1598
+ timeout: Override the client-level default timeout for this request, in seconds
1599
+
1600
+ Examples:
1601
+ from letta_client import Letta
1602
+
1603
+ client = Letta(
1604
+ token="YOUR_TOKEN",
1605
+ )
1606
+
1607
+ class InventoryItem(BaseModel):
1608
+ sku: str # Unique product identifier
1609
+ name: str # Product name
1610
+ price: float # Current price
1611
+ category: str # Product category (e.g., "Electronics", "Clothing")
1612
+
1613
+ class InventoryEntry(BaseModel):
1614
+ timestamp: int # Unix timestamp of the transaction
1615
+ item: InventoryItem # The product being updated
1616
+ transaction_id: str # Unique identifier for this inventory update
1617
+
1618
+ class InventoryEntryData(BaseModel):
1619
+ data: InventoryEntry
1620
+ quantity_change: int # Change in quantity (positive for additions, negative for removals)
1621
+
1622
+ class ManageInventoryTool(BaseTool):
1623
+ name: str = "manage_inventory"
1624
+ args_schema: Type[BaseModel] = InventoryEntryData
1625
+ description: str = "Update inventory catalogue with a new data entry"
1626
+ tags: List[str] = ["inventory", "shop"]
1627
+
1628
+ def run(self, data: InventoryEntry, quantity_change: int) -> bool:
1629
+ '''
1630
+ Implementation of the manage_inventory tool
1631
+ '''
1632
+ print(f"Updated inventory for {data.item.name} with a quantity change of {quantity_change}")
1633
+ return True
1634
+
1635
+ await client.tools.add(
1636
+ tool=ManageInventoryTool()
1637
+ )
1638
+ """
1639
+ source_code = tool.get_source_code()
1640
+ args_json_schema = tool.args_schema.model_json_schema() if tool.args_schema else None
1641
+
1642
+ # Convert PipRequirement/NpmRequirement models to Param dicts
1643
+ pip_requirements_param = (
1644
+ [typing.cast(PipRequirementParam, req.model_dump()) for req in tool.pip_requirements]
1645
+ if tool.pip_requirements
1646
+ else omit
1647
+ )
1648
+ npm_requirements_param = (
1649
+ [typing.cast(NpmRequirementParam, req.model_dump()) for req in tool.npm_requirements]
1650
+ if tool.npm_requirements
1651
+ else omit
1652
+ )
1653
+
1654
+ return await self.upsert(
1655
+ source_code=source_code,
1656
+ args_json_schema=args_json_schema or omit,
1657
+ description=tool.description or omit,
1658
+ tags=tool.tags or omit,
1659
+ source_type=tool.source_type or omit,
1660
+ json_schema=tool.json_schema or omit,
1661
+ return_char_limit=tool.return_char_limit or omit,
1662
+ pip_requirements=pip_requirements_param,
1663
+ npm_requirements=npm_requirements_param,
1664
+ default_requires_approval=tool.default_requires_approval or omit,
1665
+ extra_headers=extra_headers,
1666
+ extra_query=extra_query,
1667
+ extra_body=extra_body,
1668
+ timeout=timeout,
1669
+ )
1670
+
1071
1671
 
1072
1672
  class ToolsResourceWithRawResponse:
1073
1673
  def __init__(self, tools: ToolsResource) -> None:
@@ -1079,9 +1679,6 @@ class ToolsResourceWithRawResponse:
1079
1679
  self.retrieve = to_raw_response_wrapper(
1080
1680
  tools.retrieve,
1081
1681
  )
1082
- self.update = to_raw_response_wrapper(
1083
- tools.update,
1084
- )
1085
1682
  self.list = to_raw_response_wrapper(
1086
1683
  tools.list,
1087
1684
  )
@@ -1091,6 +1688,9 @@ class ToolsResourceWithRawResponse:
1091
1688
  self.count = to_raw_response_wrapper(
1092
1689
  tools.count,
1093
1690
  )
1691
+ self.modify = to_raw_response_wrapper(
1692
+ tools.modify,
1693
+ )
1094
1694
  self.upsert = to_raw_response_wrapper(
1095
1695
  tools.upsert,
1096
1696
  )
@@ -1109,9 +1709,6 @@ class AsyncToolsResourceWithRawResponse:
1109
1709
  self.retrieve = async_to_raw_response_wrapper(
1110
1710
  tools.retrieve,
1111
1711
  )
1112
- self.update = async_to_raw_response_wrapper(
1113
- tools.update,
1114
- )
1115
1712
  self.list = async_to_raw_response_wrapper(
1116
1713
  tools.list,
1117
1714
  )
@@ -1121,6 +1718,9 @@ class AsyncToolsResourceWithRawResponse:
1121
1718
  self.count = async_to_raw_response_wrapper(
1122
1719
  tools.count,
1123
1720
  )
1721
+ self.modify = async_to_raw_response_wrapper(
1722
+ tools.modify,
1723
+ )
1124
1724
  self.upsert = async_to_raw_response_wrapper(
1125
1725
  tools.upsert,
1126
1726
  )
@@ -1139,9 +1739,6 @@ class ToolsResourceWithStreamingResponse:
1139
1739
  self.retrieve = to_streamed_response_wrapper(
1140
1740
  tools.retrieve,
1141
1741
  )
1142
- self.update = to_streamed_response_wrapper(
1143
- tools.update,
1144
- )
1145
1742
  self.list = to_streamed_response_wrapper(
1146
1743
  tools.list,
1147
1744
  )
@@ -1151,6 +1748,9 @@ class ToolsResourceWithStreamingResponse:
1151
1748
  self.count = to_streamed_response_wrapper(
1152
1749
  tools.count,
1153
1750
  )
1751
+ self.modify = to_streamed_response_wrapper(
1752
+ tools.modify,
1753
+ )
1154
1754
  self.upsert = to_streamed_response_wrapper(
1155
1755
  tools.upsert,
1156
1756
  )
@@ -1169,9 +1769,6 @@ class AsyncToolsResourceWithStreamingResponse:
1169
1769
  self.retrieve = async_to_streamed_response_wrapper(
1170
1770
  tools.retrieve,
1171
1771
  )
1172
- self.update = async_to_streamed_response_wrapper(
1173
- tools.update,
1174
- )
1175
1772
  self.list = async_to_streamed_response_wrapper(
1176
1773
  tools.list,
1177
1774
  )
@@ -1181,6 +1778,9 @@ class AsyncToolsResourceWithStreamingResponse:
1181
1778
  self.count = async_to_streamed_response_wrapper(
1182
1779
  tools.count,
1183
1780
  )
1781
+ self.modify = async_to_streamed_response_wrapper(
1782
+ tools.modify,
1783
+ )
1184
1784
  self.upsert = async_to_streamed_response_wrapper(
1185
1785
  tools.upsert,
1186
1786
  )