flock-core 0.3.23__py3-none-any.whl → 0.3.31__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 flock-core might be problematic. Click here for more details.

Files changed (38) hide show
  1. flock/__init__.py +23 -11
  2. flock/cli/constants.py +2 -4
  3. flock/cli/create_flock.py +220 -1
  4. flock/cli/execute_flock.py +200 -0
  5. flock/cli/load_flock.py +27 -7
  6. flock/cli/loaded_flock_cli.py +202 -0
  7. flock/cli/manage_agents.py +443 -0
  8. flock/cli/view_results.py +29 -0
  9. flock/cli/yaml_editor.py +283 -0
  10. flock/core/__init__.py +2 -2
  11. flock/core/api/__init__.py +11 -0
  12. flock/core/api/endpoints.py +222 -0
  13. flock/core/api/main.py +237 -0
  14. flock/core/api/models.py +34 -0
  15. flock/core/api/run_store.py +72 -0
  16. flock/core/api/ui/__init__.py +0 -0
  17. flock/core/api/ui/routes.py +271 -0
  18. flock/core/api/ui/utils.py +119 -0
  19. flock/core/flock.py +509 -388
  20. flock/core/flock_agent.py +384 -121
  21. flock/core/flock_registry.py +532 -0
  22. flock/core/logging/logging.py +97 -23
  23. flock/core/mixin/dspy_integration.py +363 -158
  24. flock/core/serialization/__init__.py +7 -1
  25. flock/core/serialization/callable_registry.py +52 -0
  26. flock/core/serialization/serializable.py +259 -37
  27. flock/core/serialization/serialization_utils.py +199 -0
  28. flock/evaluators/declarative/declarative_evaluator.py +2 -0
  29. flock/modules/memory/memory_module.py +17 -4
  30. flock/modules/output/output_module.py +9 -3
  31. flock/workflow/activities.py +2 -2
  32. {flock_core-0.3.23.dist-info → flock_core-0.3.31.dist-info}/METADATA +6 -3
  33. {flock_core-0.3.23.dist-info → flock_core-0.3.31.dist-info}/RECORD +36 -22
  34. flock/core/flock_api.py +0 -214
  35. flock/core/registry/agent_registry.py +0 -120
  36. {flock_core-0.3.23.dist-info → flock_core-0.3.31.dist-info}/WHEEL +0 -0
  37. {flock_core-0.3.23.dist-info → flock_core-0.3.31.dist-info}/entry_points.txt +0 -0
  38. {flock_core-0.3.23.dist-info → flock_core-0.3.31.dist-info}/licenses/LICENSE +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flock-core
3
- Version: 0.3.23
3
+ Version: 0.3.31
4
4
  Summary: Declarative LLM Orchestration at Scale
5
5
  Author-email: Andre Ratzenberger <andre.ratzenberger@whiteduck.de>
6
6
  License-File: LICENSE
@@ -12,10 +12,11 @@ Requires-Dist: azure-search-documents>=11.5.2
12
12
  Requires-Dist: chromadb>=0.6.3
13
13
  Requires-Dist: cloudpickle>=3.1.1
14
14
  Requires-Dist: devtools>=0.12.2
15
- Requires-Dist: dspy==2.5.42
15
+ Requires-Dist: dspy==2.6.16
16
16
  Requires-Dist: duckduckgo-search>=7.3.2
17
17
  Requires-Dist: fastapi>=0.115.8
18
18
  Requires-Dist: httpx>=0.28.1
19
+ Requires-Dist: litellm==1.63.7
19
20
  Requires-Dist: loguru>=0.7.3
20
21
  Requires-Dist: matplotlib>=3.10.0
21
22
  Requires-Dist: msgpack>=1.1.0
@@ -33,6 +34,8 @@ Requires-Dist: pydantic>=2.10.5
33
34
  Requires-Dist: python-box>=7.3.2
34
35
  Requires-Dist: python-decouple>=3.8
35
36
  Requires-Dist: python-dotenv>=1.0.1
37
+ Requires-Dist: python-fasthtml>=0.12.6
38
+ Requires-Dist: pyyaml>=6.0
36
39
  Requires-Dist: questionary>=2.1.0
37
40
  Requires-Dist: rich>=13.9.4
38
41
  Requires-Dist: sentence-transformers>=3.4.1
@@ -59,7 +62,7 @@ Description-Content-Type: text/markdown
59
62
 
60
63
  ## Overview
61
64
 
62
- Flock is a framework for orchestrating LLM-powered agents. It leverages a **declarative approach** where you simply specify what each agent needs as input and what it produces as outputwithout having to write lengthy, brittle prompts. Under the hood, Flock transforms these declarations into robust workflows, using cutting-edge components such as Temporal and DSPy to handle fault tolerance, state management, and error recovery.
65
+ Flock is a framework for orchestrating LLM-powered agents. It leverages a **declarative approach** where you simply specify what each agent needs as input and what it produces as output, without having to write lengthy, brittle prompts. Under the hood, Flock transforms these declarations into robust workflows, using cutting-edge components such as Temporal and DSPy to handle fault tolerance, state management, and error recovery.
63
66
 
64
67
 
65
68
 
@@ -1,22 +1,35 @@
1
- flock/__init__.py,sha256=49_Z1uLb-fA2InJtNHQleB3NDpfamZGq2S01yttJoVI,2122
1
+ flock/__init__.py,sha256=TCFm-Ax0MINIW3-4KdaiGz36raTENp_AY68eO8_a_rQ,2574
2
2
  flock/config.py,sha256=O5QJGlStf4DWSK4ovZsKw01ud4YK3_ij6Ay8sWU8ih0,1522
3
- flock/cli/constants.py,sha256=UWshD25IGos5Ks4P9paGPalY8BXy9YynzHk6HB4xfOo,669
3
+ flock/cli/constants.py,sha256=s2Mird8E0QXqPH1xG8gxG7rXYY0F4eftGfbBC5ceG2k,568
4
4
  flock/cli/create_agent.py,sha256=DkeLUlrb7rGx3nZ04aADU9HXXu5mZTf_DBwT0xhzIv4,7
5
- flock/cli/create_flock.py,sha256=DkeLUlrb7rGx3nZ04aADU9HXXu5mZTf_DBwT0xhzIv4,7
5
+ flock/cli/create_flock.py,sha256=Lry15fAwvnh0rHl1pIJ1xKqVj-nYBteNAE1G83LRaAo,6123
6
+ flock/cli/execute_flock.py,sha256=rAP-5nFfyOivi5uWG8mloZwXF9Tj9iD8MYSbllPllQ4,5726
6
7
  flock/cli/load_agent.py,sha256=DkeLUlrb7rGx3nZ04aADU9HXXu5mZTf_DBwT0xhzIv4,7
7
8
  flock/cli/load_examples.py,sha256=DkeLUlrb7rGx3nZ04aADU9HXXu5mZTf_DBwT0xhzIv4,7
8
- flock/cli/load_flock.py,sha256=3JdECvt5X7uyOG2vZS3-Zk5C5SI_84_QZjcsB3oJmfA,932
9
+ flock/cli/load_flock.py,sha256=5bsdjO5olLtpnFEl_UfisnwR8iSQAkOIWI49tnSwJHc,1537
9
10
  flock/cli/load_release_notes.py,sha256=qFcgUrMddAE_TP6x1P-6ZywTUjTknfhTDW5LTxtg1yk,599
11
+ flock/cli/loaded_flock_cli.py,sha256=LXjvTjxt84VG67wBfownICGTbzx0Z2JmCOKAg_L2a6Q,5913
12
+ flock/cli/manage_agents.py,sha256=wkNF0IqNFfePrFueR57SILPW885IPqs3U8Cp-fcPPmo,12710
10
13
  flock/cli/settings.py,sha256=Z_TXBzCYlCmSaKrJ_CQCdYy-Cj29gpI4kbC_2KzoKqg,27025
14
+ flock/cli/view_results.py,sha256=dOzK0O1FHSIDERnx48y-2Xke9BkOHS7pcOhs64AyIg0,781
15
+ flock/cli/yaml_editor.py,sha256=VpaSwC-Xcbu_gk4HgUeIL7PXNFu1CdstuJ3mRZOkmIk,8096
11
16
  flock/cli/assets/release_notes.md,sha256=bqnk50jxM3w5uY44Dc7MkdT8XmRREFxrVBAG9XCOSSU,4896
12
- flock/core/__init__.py,sha256=mPlvKc0SxC2qCvSlgYeP_7EyV8ptmdn24NO8mlQoCSo,559
13
- flock/core/flock.py,sha256=IURlcuNvdsnqKkvgXtX4v_pGWQ8Lfb60X--MT0zvxHo,19881
14
- flock/core/flock_agent.py,sha256=F1wl54ivLQijSHlv_Q_znw_ElzdDlqpi-KugVUyHTRE,12238
15
- flock/core/flock_api.py,sha256=2rHnmEdtT5KPZYwGesRT7LqwbrgKClODHT-O56u7pcQ,7140
17
+ flock/core/__init__.py,sha256=6NmSXsdQOoOPWjWqdF8BYiUveb54CjH8Ta0WAjNM0Ps,574
18
+ flock/core/flock.py,sha256=iUHelhSO85qQclHbiJfQzLRepwUFcf3DGBDnrOwgzsM,23722
19
+ flock/core/flock_agent.py,sha256=jkDwB7yVGYyLfg-WuwvR2X4XblXOs5DrB2dB30xBL7Q,24754
16
20
  flock/core/flock_evaluator.py,sha256=dOXZeDOGZcAmJ9ahqq_2bdGUU1VOXY4skmwTVpAjiVw,1685
17
21
  flock/core/flock_factory.py,sha256=MGTkJCP1WGpV614f87r1vwe0tqAvBCoH9PlqtqDyJDk,2828
18
22
  flock/core/flock_module.py,sha256=96aFVYAgwpKN53xGbivQDUpikOYGFCxK5mqhclOcxY0,3003
23
+ flock/core/flock_registry.py,sha256=vQ0N8WSBwOaMLicfmCuFmmOn5ORdF1WhDAJC1BqcHkA,19438
19
24
  flock/core/flock_router.py,sha256=A5GaxcGvtiFlRLHBTW7okh5RDm3BdKam2uXvRHRaj7k,2187
25
+ flock/core/api/__init__.py,sha256=OKlhzDWZJfA6ddBwxQUmATY0TSzESsH032u00iVGvdA,228
26
+ flock/core/api/endpoints.py,sha256=m-QAyizCHGh3sd5IXaDEhquSxNgTZLpUVTXLdVjiDVw,9086
27
+ flock/core/api/main.py,sha256=-MJClTcmkyUnaP9fmVu2CcHagFy_9lKk6CAbF05kraY,8928
28
+ flock/core/api/models.py,sha256=mMPCMCD52Txc56_yscwZQG0RRPCJTnIrVKQ8WbI7gts,1111
29
+ flock/core/api/run_store.py,sha256=kmrb0bq2Et5JiSxFWskAAf5a4jTeEFVZShTDlX5jfAk,2773
30
+ flock/core/api/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
+ flock/core/api/ui/routes.py,sha256=nS-wWO94mshE5ozWfOQZ-HOvtes_1qxDVcqpMZtU5JQ,8885
32
+ flock/core/api/ui/utils.py,sha256=V7PqYHNK519hFJ8jvvwf7bGpbBXCRz_HQG3BDCCqlNA,4802
20
33
  flock/core/context/context.py,sha256=8bjRLZ74oacRNBaHmDNXdQKfB-95poF7Pp03n2k0zcQ,6437
21
34
  flock/core/context/context_manager.py,sha256=FANSWa6DEhdhtZ7t_9Gza0v80UdpoDOhHbfVOccmjkA,1181
22
35
  flock/core/context/context_vars.py,sha256=zYTMi9b6mNSSEHowEQUOTpEDurmAjaUcyBCgfKY6-cU,300
@@ -24,7 +37,7 @@ flock/core/execution/local_executor.py,sha256=rnIQvaJOs6zZORUcR3vvyS6LPREDJTjayg
24
37
  flock/core/execution/temporal_executor.py,sha256=OF_uXgQsoUGp6U1ZkcuaidAEKyH7XDtbfrtdF10XQ_4,1675
25
38
  flock/core/interpreter/python_interpreter.py,sha256=RaUMZuufsKBNQ4FAeSaOgUuxzs8VYu5TgUUs-xwaxxM,26376
26
39
  flock/core/logging/__init__.py,sha256=Q8hp9-1ilPIUIV0jLgJ3_cP7COrea32cVwL7dicPnlM,82
27
- flock/core/logging/logging.py,sha256=uWtUZnQI_sdtzLfXo61JPENSNNwplvEuGMPIhsYd-gQ,12448
40
+ flock/core/logging/logging.py,sha256=-ViLNLTm5wqbvVsc6xYekOsAY38ZCIn6j1wciC7lgeM,15417
28
41
  flock/core/logging/telemetry.py,sha256=3E9Tyj6AUR6A5RlIufcdCdWm5BAA7tbOsCa7lHoUQaU,5404
29
42
  flock/core/logging/trace_and_logged.py,sha256=5vNrK1kxuPMoPJ0-QjQg-EDJL1oiEzvU6UNi6X8FiMs,2117
30
43
  flock/core/logging/formatters/enum_builder.py,sha256=LgEYXUv84wK5vwHflZ5h8HBGgvLH3sByvUQe8tZiyY0,981
@@ -35,13 +48,14 @@ flock/core/logging/span_middleware/baggage_span_processor.py,sha256=gJfRl8FeB6jd
35
48
  flock/core/logging/telemetry_exporter/base_exporter.py,sha256=rQJJzS6q9n2aojoSqwCnl7ZtHrh5LZZ-gkxUuI5WfrQ,1124
36
49
  flock/core/logging/telemetry_exporter/file_exporter.py,sha256=nKAjJSZtA7FqHSTuTiFtYYepaxOq7l1rDvs8U8rSBlA,3023
37
50
  flock/core/logging/telemetry_exporter/sqlite_exporter.py,sha256=CDsiMb9QcqeXelZ6ZqPSS56ovMPGqOu6whzBZRK__Vg,3498
38
- flock/core/mixin/dspy_integration.py,sha256=P5G4Y04nl5hFwFbJXCkQ-0TMR1L4skLL2IM_FlUjH_c,8364
51
+ flock/core/mixin/dspy_integration.py,sha256=vlf6rJnR9EsfZi5KyFLEXIbUvhpBhodctn-mirYo7Pk,17382
39
52
  flock/core/mixin/prompt_parser.py,sha256=eOqI-FK3y17gVqpc_y5GF-WmK1Jv8mFlkZxTcgweoxI,5121
40
- flock/core/registry/agent_registry.py,sha256=TUClh9e3eA6YzZC1CMTlsTPvQeqb9jYHewi-zPpcWM8,4987
41
- flock/core/serialization/__init__.py,sha256=j0uw1g-7SOEhD5Ozgc8WpbZNpDWRmu58UOGg4_QTu8U,320
53
+ flock/core/serialization/__init__.py,sha256=CML7fPgG6p4c0CDBlJ_uwV1aZZhJKK9uy3IoIHfO87w,431
54
+ flock/core/serialization/callable_registry.py,sha256=sUZECTZWsM3fJ8FDRQ-FgLNW9hF26nY17AD6fJKADMc,1419
42
55
  flock/core/serialization/json_encoder.py,sha256=gAKj2zU_8wQiNvdkby2hksSA4fbPNwTjup_yz1Le1Vw,1229
43
56
  flock/core/serialization/secure_serializer.py,sha256=n5-zRvvXddgJv1FFHsaQ2wuYdL3WUSGPvG_LGaffEJo,6144
44
- flock/core/serialization/serializable.py,sha256=SymJ0YrjBx48mOBItYSqoRpKuzIc4vKWRS6ScTzre7s,2573
57
+ flock/core/serialization/serializable.py,sha256=ymuJmm8teLbyUFMakkD7W3a_N8H4igZ1ITQnOqoLt0o,11270
58
+ flock/core/serialization/serialization_utils.py,sha256=YxlPoHFPtj5otWUlKEsKphWxnd_d6b8yMZN_5MDlzB4,7577
45
59
  flock/core/tools/azure_tools.py,sha256=9Bi6IrB5pzBTBhBSxpCVMgx8HBud8nl4gDp8aN0NT6c,17031
46
60
  flock/core/tools/basic_tools.py,sha256=hEG14jNZ2itVvubCHTfsWkuJK6yuNwBtuFj2Js0VHZs,9043
47
61
  flock/core/tools/llm_tools.py,sha256=Bdt4Dpur5dGpxd2KFEQyxjfZazvW1HCDKY6ydMj6UgQ,21811
@@ -50,17 +64,17 @@ flock/core/tools/dev_tools/github.py,sha256=a2OTPXS7kWOVA4zrZHynQDcsmEi4Pac5MfSj
50
64
  flock/core/util/cli_helper.py,sha256=QSpP10WRNcjXzVFwpTQA8lSBy7707Qlv7uCit1XjUms,49808
51
65
  flock/core/util/hydrator.py,sha256=6qNwOwCZB7r6y25BZ--0PGofrAlfMaXbDKFQeP5NLts,11196
52
66
  flock/core/util/input_resolver.py,sha256=g9vDPdY4OH-G7qjas5ksGEHueokHGFPMoLOvC-ngeLo,5984
53
- flock/evaluators/declarative/declarative_evaluator.py,sha256=f8ldgZZp94zC4CoGzBufKvbvtckCGBe9EHTOoAZfZK0,1695
67
+ flock/evaluators/declarative/declarative_evaluator.py,sha256=WZ74LG81JcuApG2KcTk8plh0fFqDhJjtl6ubW1K-fqc,1750
54
68
  flock/evaluators/memory/azure_search_evaluator.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
69
  flock/evaluators/memory/memory_evaluator.py,sha256=SmerXyNaqm8DTV0yw-WqWkn9DXIf6x-nPG1eyTV6NY8,3452
56
70
  flock/evaluators/natural_language/natural_language_evaluator.py,sha256=6nVEeh8_uwv_h-d3FWlA0GbzDzRtdhvxCGKirHtyvOU,2012
57
71
  flock/evaluators/zep/zep_evaluator.py,sha256=9NOELl7JAuUcx_FQrxY6b-_vN3MjwDyW7ZppPIGeCFc,1954
58
72
  flock/modules/azure-search/azure_search_module.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
73
  flock/modules/callback/callback_module.py,sha256=volGGgHtY19qj1wHR6m5a_hmXSbV3Ca3uY6I76YmcfU,2833
60
- flock/modules/memory/memory_module.py,sha256=dZ30eOFqIlAz0a5IKJMoXgJ-VyPEqApAOX0OQjhGA1I,14733
74
+ flock/modules/memory/memory_module.py,sha256=bSkdFBW-Pp5ldHhXi8v4kfRM7zknfLR2fsOtbTosucI,14916
61
75
  flock/modules/memory/memory_parser.py,sha256=FLH7GL8XThvHiCMfX3eQH7Sz-f62fzhAUmO6_gaDI7U,4372
62
76
  flock/modules/memory/memory_storage.py,sha256=CNcLDMmvv0x7Z3YMKr6VveS_VCa7rKPw8l2d-XgqokA,27246
63
- flock/modules/output/output_module.py,sha256=kfHlnhdECC2k7uF_0VZ9_152zHI0qHJ2ZqGwYSsnoro,7621
77
+ flock/modules/output/output_module.py,sha256=wOXMCyldFslj2iCMn2W5VZrSHCauMXwsW7YoFEHEcLY,7846
64
78
  flock/modules/performance/metrics_module.py,sha256=UD9OjY4-zAvauMD7YyDYqE1gyIhzpdr3JkBT8j9knxY,16790
65
79
  flock/modules/zep/zep_module.py,sha256=x7JG6O6xnwwum0RETIqKYbA3xzdcvX2aUuns0Cl0c2Q,6014
66
80
  flock/platform/docker_tools.py,sha256=fpA7-6rJBjPOUBLdQP4ny2QPgJ_042nmqRn5GtKnoYw,1445
@@ -410,12 +424,12 @@ flock/themes/zenburned.toml,sha256=UEmquBbcAO3Zj652XKUwCsNoC2iQSlIh-q5c6DH-7Kc,1
410
424
  flock/themes/zenwritten-dark.toml,sha256=To5l6520_3UqAGiEumpzGWsHhXxqu9ThrMildXKgIO0,1669
411
425
  flock/themes/zenwritten-light.toml,sha256=G1iEheCPfBNsMTGaVpEVpDzYBHA_T-MV27rolUYolmE,1666
412
426
  flock/workflow/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
413
- flock/workflow/activities.py,sha256=yah-lHjMW6_Ww1gt7hMXBis1cJRlcbHx0uLsMB9oNZ0,9066
427
+ flock/workflow/activities.py,sha256=eVZDnxGJl_quNO-UTV3YgvTV8LrRaHN3QDAA1ANKzac,9065
414
428
  flock/workflow/agent_activities.py,sha256=NhBZscflEf2IMfSRa_pBM_TRP7uVEF_O0ROvWZ33eDc,963
415
429
  flock/workflow/temporal_setup.py,sha256=VWBgmBgfTBjwM5ruS_dVpA5AVxx6EZ7oFPGw4j3m0l0,1091
416
430
  flock/workflow/workflow.py,sha256=I9MryXW_bqYVTHx-nl2epbTqeRy27CAWHHA7ZZA0nAk,1696
417
- flock_core-0.3.23.dist-info/METADATA,sha256=qwn0OaG4E4j-5vjAPcqSv6jqpxtL8e5NcuhyHgKHkCY,20649
418
- flock_core-0.3.23.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
419
- flock_core-0.3.23.dist-info/entry_points.txt,sha256=rWaS5KSpkTmWySURGFZk6PhbJ87TmvcFQDi2uzjlagQ,37
420
- flock_core-0.3.23.dist-info/licenses/LICENSE,sha256=iYEqWy0wjULzM9GAERaybP4LBiPeu7Z1NEliLUdJKSc,1072
421
- flock_core-0.3.23.dist-info/RECORD,,
431
+ flock_core-0.3.31.dist-info/METADATA,sha256=wWrCmQuj7lyJu1mmgezo7gmkgjwyGh8HC3i-4DyF2xI,20745
432
+ flock_core-0.3.31.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
433
+ flock_core-0.3.31.dist-info/entry_points.txt,sha256=rWaS5KSpkTmWySURGFZk6PhbJ87TmvcFQDi2uzjlagQ,37
434
+ flock_core-0.3.31.dist-info/licenses/LICENSE,sha256=iYEqWy0wjULzM9GAERaybP4LBiPeu7Z1NEliLUdJKSc,1072
435
+ flock_core-0.3.31.dist-info/RECORD,,
flock/core/flock_api.py DELETED
@@ -1,214 +0,0 @@
1
- """REST API server for Flock."""
2
-
3
- import uuid
4
- from datetime import datetime
5
- from typing import Any
6
-
7
- import uvicorn
8
- from fastapi import BackgroundTasks, FastAPI, HTTPException
9
- from pydantic import BaseModel, Field
10
-
11
- from flock.core.flock import Flock
12
- from flock.core.logging.logging import get_logger
13
-
14
- logger = get_logger("api")
15
-
16
-
17
- class FlockAPIRequest(BaseModel):
18
- """Request model for running an agent."""
19
-
20
- agent_name: str = Field(..., description="Name of the agent to run")
21
- inputs: dict[str, Any] = Field(
22
- default_factory=dict, description="Input data for the agent"
23
- )
24
- async_run: bool = Field(
25
- default=False, description="Whether to run asynchronously"
26
- )
27
-
28
-
29
- class FlockAPIResponse(BaseModel):
30
- """Response model for run requests."""
31
-
32
- run_id: str = Field(..., description="Unique ID for this run")
33
- status: str = Field(..., description="Status of the run")
34
- result: dict[str, Any] | None = Field(
35
- None, description="Run result if completed"
36
- )
37
- started_at: datetime = Field(..., description="When the run started")
38
- completed_at: datetime | None = Field(
39
- None, description="When the run completed"
40
- )
41
- error: str | None = Field(None, description="Error message if failed")
42
-
43
-
44
- class FlockAPI:
45
- """REST API server for Flock.
46
-
47
- Provides HTTP endpoints for:
48
- - Running agents
49
- - Checking run status
50
- - Getting run results
51
- """
52
-
53
- def __init__(self, flock: Flock):
54
- self.flock = flock
55
- self.app = FastAPI(title="Flock API")
56
- self.runs: dict[str, FlockAPIResponse] = {}
57
-
58
- # Register routes
59
- self._setup_routes()
60
-
61
- def _setup_routes(self):
62
- """Set up API routes."""
63
-
64
- @self.app.post("/run/flock", response_model=FlockAPIResponse)
65
- async def run_flock(
66
- request: FlockAPIRequest, background_tasks: BackgroundTasks
67
- ):
68
- """Run an agent with the provided inputs."""
69
- try:
70
- # Generate run ID
71
- run_id = str(uuid.uuid4())
72
-
73
- # Create initial response
74
- response = FlockAPIResponse(
75
- run_id=run_id, status="starting", started_at=datetime.now()
76
- )
77
- self.runs[run_id] = response
78
-
79
- if request.async_run:
80
- # Start run in background
81
- background_tasks.add_task(
82
- self._run_flock,
83
- run_id,
84
- request.agent_name,
85
- request.inputs,
86
- )
87
- response.status = "running"
88
- else:
89
- # Run synchronously
90
- await self._run_flock(
91
- run_id, request.agent_name, request.inputs
92
- )
93
-
94
- return self.runs[run_id]
95
-
96
- except Exception as e:
97
- logger.error(f"Error starting run: {e!s}")
98
- raise HTTPException(status_code=500, detail=str(e))
99
-
100
- @self.app.post("/run/agent", response_model=FlockAPIResponse)
101
- async def run_agent(
102
- request: FlockAPIRequest, background_tasks: BackgroundTasks
103
- ):
104
- """Run an agent with the provided inputs."""
105
- try:
106
- # Generate run ID
107
- run_id = str(uuid.uuid4())
108
-
109
- # Create initial response
110
- response = FlockAPIResponse(
111
- run_id=run_id, status="starting", started_at=datetime.now()
112
- )
113
- self.runs[run_id] = response
114
-
115
- if request.async_run:
116
- # Start run in background
117
- background_tasks.add_task(
118
- self._run_agent,
119
- run_id,
120
- request.agent_name,
121
- request.inputs,
122
- )
123
- response.status = "running"
124
- else:
125
- # Run synchronously
126
- await self._run_agent(
127
- run_id, request.agent_name, request.inputs
128
- )
129
-
130
- return self.runs[run_id]
131
-
132
- except Exception as e:
133
- logger.error(f"Error starting run: {e!s}")
134
- raise HTTPException(status_code=500, detail=str(e))
135
-
136
- @self.app.get("/run/{run_id}", response_model=FlockAPIResponse)
137
- async def get_run_status(run_id: str):
138
- """Get the status of a run."""
139
- if run_id not in self.runs:
140
- raise HTTPException(status_code=404, detail="Run not found")
141
- return self.runs[run_id]
142
-
143
- @self.app.get("/agents")
144
- async def list_agents():
145
- """List all available agents."""
146
- return {
147
- "agents": [
148
- {
149
- "name": agent.name,
150
- "description": agent.description,
151
- "input_schema": agent.input,
152
- "output_schema": agent.output,
153
- }
154
- for agent in self.flock.agents.values()
155
- ]
156
- }
157
-
158
- async def _run_agent(
159
- self, run_id: str, agent_name: str, inputs: dict[str, Any]
160
- ):
161
- """Execute an agent run."""
162
- try:
163
- # Get the agent
164
- if agent_name not in self.flock.agents:
165
- raise ValueError(f"Agent '{agent_name}' not found")
166
-
167
- agent = self.flock.agents[agent_name]
168
-
169
- # Run the agent
170
- result = await agent.run_async(inputs)
171
-
172
- # Update run status
173
- self.runs[run_id].status = "completed"
174
- self.runs[run_id].result = result
175
- self.runs[run_id].completed_at = datetime.now()
176
-
177
- except Exception as e:
178
- logger.error(f"Error in run {run_id}: {e!s}")
179
- self.runs[run_id].status = "failed"
180
- self.runs[run_id].error = str(e)
181
- self.runs[run_id].completed_at = datetime.now()
182
-
183
- async def _run_flock(
184
- self, run_id: str, agent_name: str, inputs: dict[str, Any]
185
- ):
186
- """Execute an agent run."""
187
- try:
188
- # Get the agent
189
- if agent_name not in self.flock.agents:
190
- raise ValueError(f"Agent '{agent_name}' not found")
191
-
192
- result = await self.flock.run_async(
193
- start_agent=agent_name, input=inputs
194
- )
195
-
196
- # Update run status
197
- self.runs[run_id].status = "completed"
198
- self.runs[run_id].result = result
199
- self.runs[run_id].completed_at = datetime.now()
200
-
201
- except Exception as e:
202
- logger.error(f"Error in run {run_id}: {e!s}")
203
- self.runs[run_id].status = "failed"
204
- self.runs[run_id].error = str(e)
205
- self.runs[run_id].completed_at = datetime.now()
206
-
207
- def start(self, host: str = "0.0.0.0", port: int = 8344):
208
- """Start the API server."""
209
- uvicorn.run(self.app, host=host, port=port)
210
-
211
- async def stop(self):
212
- """Stop the API server."""
213
- # Cleanup if needed
214
- pass
@@ -1,120 +0,0 @@
1
- """Registry for storing and managing agents and tools with logging and tracing integration."""
2
-
3
- from collections.abc import Callable
4
-
5
- from opentelemetry import trace
6
-
7
- from flock.core.flock_agent import FlockAgent
8
- from flock.core.flock_module import FlockModule
9
- from flock.core.logging.logging import get_logger
10
-
11
- logger = get_logger("registry")
12
- tracer = trace.get_tracer(__name__)
13
-
14
-
15
- class Registry:
16
- """Registry for storing and managing agents and tools.
17
-
18
- This singleton class maintains a centralized registry of agents and tools,
19
- which is particularly important for Temporal workflows where only basic Python
20
- types can be passed between activities.
21
- """
22
-
23
- _instance = None
24
-
25
- def __new__(cls):
26
- with tracer.start_as_current_span("Registry.__new__") as span:
27
- if cls._instance is None:
28
- cls._instance = super().__new__(cls)
29
- cls._instance._initialize()
30
- logger.info("Registry instance created")
31
- span.set_attribute("instance.created", True)
32
- return cls._instance
33
-
34
- def _initialize(self):
35
- with tracer.start_as_current_span("Registry._initialize"):
36
- self._agents: list[FlockAgent] = []
37
- self._tools: list[tuple[str, Callable]] = []
38
- self._modules: list[FlockModule] = []
39
- logger.info("Registry initialized", agents_count=0, tools_count=0)
40
-
41
- def register_tool(self, tool_name: str, tool: Callable) -> None:
42
- with tracer.start_as_current_span("Registry.register_tool") as span:
43
- span.set_attribute("tool_name", tool_name)
44
- try:
45
- self._tools.append((tool_name, tool))
46
- logger.info("Tool registered", tool_name=tool_name)
47
- except Exception as e:
48
- logger.error(
49
- "Error registering tool", tool_name=tool_name, error=str(e)
50
- )
51
- span.record_exception(e)
52
- raise
53
-
54
- def register_agent(self, agent: FlockAgent) -> None:
55
- with tracer.start_as_current_span("Registry.register_agent") as span:
56
- span.set_attribute("agent_name", agent.name)
57
- try:
58
- self._agents.append(agent)
59
- logger.info("Agent registered", agent=agent.name)
60
- except Exception as e:
61
- logger.error(
62
- "Error registering agent", agent=agent.name, error=str(e)
63
- )
64
- span.record_exception(e)
65
- raise
66
-
67
- def get_agent(self, name: str) -> FlockAgent | None:
68
- with tracer.start_as_current_span("Registry.get_agent") as span:
69
- span.set_attribute("search_agent_name", name)
70
- try:
71
- for agent in self._agents:
72
- if agent.name == name:
73
- logger.info("Agent found", agent=name)
74
- span.set_attribute("found", True)
75
- return agent
76
- logger.warning("Agent not found", agent=name)
77
- span.set_attribute("found", False)
78
- return None
79
- except Exception as e:
80
- logger.error("Error retrieving agent", agent=name, error=str(e))
81
- span.record_exception(e)
82
- raise
83
-
84
- def get_tool(self, name: str) -> Callable | None:
85
- with tracer.start_as_current_span("Registry.get_tool") as span:
86
- span.set_attribute("search_tool_name", name)
87
- try:
88
- for tool_name, tool in self._tools:
89
- if tool_name == name:
90
- logger.info("Tool found", tool=name)
91
- span.set_attribute("found", True)
92
- return tool
93
- logger.warning("Tool not found", tool=name)
94
- span.set_attribute("found", False)
95
- return None
96
- except Exception as e:
97
- logger.error("Error retrieving tool", tool=name, error=str(e))
98
- span.record_exception(e)
99
- raise
100
-
101
- def get_tools(self, names: list[str] | None) -> list[Callable]:
102
- with tracer.start_as_current_span("Registry.get_tools") as span:
103
- span.set_attribute("search_tool_names", str(names))
104
- try:
105
- if not names:
106
- logger.info("No tool names provided")
107
- return []
108
- tools = [self.get_tool(name) for name in names]
109
- found_tools = [tool for tool in tools if tool is not None]
110
- logger.info(
111
- "Tools retrieved", requested=names, found=len(found_tools)
112
- )
113
- span.set_attribute("found_tools_count", len(found_tools))
114
- return found_tools
115
- except Exception as e:
116
- logger.error(
117
- "Error retrieving tools", names=str(names), error=str(e)
118
- )
119
- span.record_exception(e)
120
- raise