soe-ai 0.2.0b1__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.
Files changed (145) hide show
  1. soe/__init__.py +50 -0
  2. soe/broker.py +168 -0
  3. soe/builtin_tools/__init__.py +51 -0
  4. soe/builtin_tools/soe_add_signal.py +82 -0
  5. soe/builtin_tools/soe_call_tool.py +111 -0
  6. soe/builtin_tools/soe_copy_context.py +80 -0
  7. soe/builtin_tools/soe_explore_docs.py +290 -0
  8. soe/builtin_tools/soe_get_available_tools.py +42 -0
  9. soe/builtin_tools/soe_get_context.py +50 -0
  10. soe/builtin_tools/soe_get_context_schema.py +56 -0
  11. soe/builtin_tools/soe_get_identities.py +63 -0
  12. soe/builtin_tools/soe_get_workflows.py +63 -0
  13. soe/builtin_tools/soe_inject_context_schema_field.py +80 -0
  14. soe/builtin_tools/soe_inject_identity.py +64 -0
  15. soe/builtin_tools/soe_inject_node.py +86 -0
  16. soe/builtin_tools/soe_inject_workflow.py +105 -0
  17. soe/builtin_tools/soe_list_contexts.py +73 -0
  18. soe/builtin_tools/soe_remove_context_schema_field.py +61 -0
  19. soe/builtin_tools/soe_remove_identity.py +61 -0
  20. soe/builtin_tools/soe_remove_node.py +72 -0
  21. soe/builtin_tools/soe_remove_workflow.py +62 -0
  22. soe/builtin_tools/soe_update_context.py +54 -0
  23. soe/docs/_config.yml +10 -0
  24. soe/docs/advanced_patterns/guide_fanout_and_aggregations.md +318 -0
  25. soe/docs/advanced_patterns/guide_inheritance.md +435 -0
  26. soe/docs/advanced_patterns/hybrid_intelligence.md +237 -0
  27. soe/docs/advanced_patterns/index.md +49 -0
  28. soe/docs/advanced_patterns/operational.md +781 -0
  29. soe/docs/advanced_patterns/self_evolving_workflows.md +385 -0
  30. soe/docs/advanced_patterns/swarm_intelligence.md +211 -0
  31. soe/docs/builtins/context.md +164 -0
  32. soe/docs/builtins/context_schema.md +158 -0
  33. soe/docs/builtins/identity.md +139 -0
  34. soe/docs/builtins/soe_explore_docs.md +135 -0
  35. soe/docs/builtins/tools.md +164 -0
  36. soe/docs/builtins/workflows.md +199 -0
  37. soe/docs/guide_00_getting_started.md +341 -0
  38. soe/docs/guide_01_tool.md +206 -0
  39. soe/docs/guide_02_llm.md +143 -0
  40. soe/docs/guide_03_router.md +146 -0
  41. soe/docs/guide_04_patterns.md +475 -0
  42. soe/docs/guide_05_agent.md +159 -0
  43. soe/docs/guide_06_schema.md +397 -0
  44. soe/docs/guide_07_identity.md +540 -0
  45. soe/docs/guide_08_child.md +612 -0
  46. soe/docs/guide_09_ecosystem.md +690 -0
  47. soe/docs/guide_10_infrastructure.md +427 -0
  48. soe/docs/guide_11_builtins.md +126 -0
  49. soe/docs/index.md +104 -0
  50. soe/docs/primitives/backends.md +281 -0
  51. soe/docs/primitives/context.md +256 -0
  52. soe/docs/primitives/node_reference.md +259 -0
  53. soe/docs/primitives/primitives.md +331 -0
  54. soe/docs/primitives/signals.md +865 -0
  55. soe/docs_index.py +2 -0
  56. soe/init.py +165 -0
  57. soe/lib/__init__.py +0 -0
  58. soe/lib/child_context.py +46 -0
  59. soe/lib/context_fields.py +51 -0
  60. soe/lib/inheritance.py +172 -0
  61. soe/lib/jinja_render.py +113 -0
  62. soe/lib/operational.py +51 -0
  63. soe/lib/parent_sync.py +71 -0
  64. soe/lib/register_event.py +75 -0
  65. soe/lib/schema_validation.py +134 -0
  66. soe/lib/yaml_parser.py +14 -0
  67. soe/local_backends/__init__.py +18 -0
  68. soe/local_backends/factory.py +124 -0
  69. soe/local_backends/in_memory/context.py +38 -0
  70. soe/local_backends/in_memory/conversation_history.py +60 -0
  71. soe/local_backends/in_memory/identity.py +52 -0
  72. soe/local_backends/in_memory/schema.py +40 -0
  73. soe/local_backends/in_memory/telemetry.py +38 -0
  74. soe/local_backends/in_memory/workflow.py +33 -0
  75. soe/local_backends/storage/context.py +57 -0
  76. soe/local_backends/storage/conversation_history.py +82 -0
  77. soe/local_backends/storage/identity.py +118 -0
  78. soe/local_backends/storage/schema.py +96 -0
  79. soe/local_backends/storage/telemetry.py +72 -0
  80. soe/local_backends/storage/workflow.py +56 -0
  81. soe/nodes/__init__.py +13 -0
  82. soe/nodes/agent/__init__.py +10 -0
  83. soe/nodes/agent/factory.py +134 -0
  84. soe/nodes/agent/lib/loop_handlers.py +150 -0
  85. soe/nodes/agent/lib/loop_state.py +157 -0
  86. soe/nodes/agent/lib/prompts.py +65 -0
  87. soe/nodes/agent/lib/tools.py +35 -0
  88. soe/nodes/agent/stages/__init__.py +12 -0
  89. soe/nodes/agent/stages/parameter.py +37 -0
  90. soe/nodes/agent/stages/response.py +54 -0
  91. soe/nodes/agent/stages/router.py +37 -0
  92. soe/nodes/agent/state.py +111 -0
  93. soe/nodes/agent/types.py +66 -0
  94. soe/nodes/agent/validation/__init__.py +11 -0
  95. soe/nodes/agent/validation/config.py +95 -0
  96. soe/nodes/agent/validation/operational.py +24 -0
  97. soe/nodes/child/__init__.py +3 -0
  98. soe/nodes/child/factory.py +61 -0
  99. soe/nodes/child/state.py +59 -0
  100. soe/nodes/child/validation/__init__.py +11 -0
  101. soe/nodes/child/validation/config.py +126 -0
  102. soe/nodes/child/validation/operational.py +28 -0
  103. soe/nodes/lib/conditions.py +71 -0
  104. soe/nodes/lib/context.py +24 -0
  105. soe/nodes/lib/conversation_history.py +77 -0
  106. soe/nodes/lib/identity.py +64 -0
  107. soe/nodes/lib/llm_resolver.py +142 -0
  108. soe/nodes/lib/output.py +68 -0
  109. soe/nodes/lib/response_builder.py +91 -0
  110. soe/nodes/lib/signal_emission.py +79 -0
  111. soe/nodes/lib/signals.py +54 -0
  112. soe/nodes/lib/tools.py +100 -0
  113. soe/nodes/llm/__init__.py +7 -0
  114. soe/nodes/llm/factory.py +103 -0
  115. soe/nodes/llm/state.py +76 -0
  116. soe/nodes/llm/types.py +12 -0
  117. soe/nodes/llm/validation/__init__.py +11 -0
  118. soe/nodes/llm/validation/config.py +89 -0
  119. soe/nodes/llm/validation/operational.py +23 -0
  120. soe/nodes/router/__init__.py +3 -0
  121. soe/nodes/router/factory.py +37 -0
  122. soe/nodes/router/state.py +32 -0
  123. soe/nodes/router/validation/__init__.py +11 -0
  124. soe/nodes/router/validation/config.py +58 -0
  125. soe/nodes/router/validation/operational.py +16 -0
  126. soe/nodes/tool/factory.py +66 -0
  127. soe/nodes/tool/lib/__init__.py +11 -0
  128. soe/nodes/tool/lib/conditions.py +35 -0
  129. soe/nodes/tool/lib/failure.py +28 -0
  130. soe/nodes/tool/lib/parameters.py +67 -0
  131. soe/nodes/tool/state.py +66 -0
  132. soe/nodes/tool/types.py +27 -0
  133. soe/nodes/tool/validation/__init__.py +15 -0
  134. soe/nodes/tool/validation/config.py +132 -0
  135. soe/nodes/tool/validation/operational.py +16 -0
  136. soe/types.py +209 -0
  137. soe/validation/__init__.py +18 -0
  138. soe/validation/config.py +195 -0
  139. soe/validation/jinja.py +54 -0
  140. soe/validation/operational.py +110 -0
  141. soe_ai-0.2.0b1.dist-info/METADATA +262 -0
  142. soe_ai-0.2.0b1.dist-info/RECORD +145 -0
  143. soe_ai-0.2.0b1.dist-info/WHEEL +5 -0
  144. soe_ai-0.2.0b1.dist-info/licenses/LICENSE +21 -0
  145. soe_ai-0.2.0b1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,64 @@
1
+ """Built-in identity injection tool."""
2
+
3
+ from typing import Dict, Any, Callable
4
+ from ..types import EventTypes
5
+ from ..lib.register_event import register_event
6
+
7
+
8
+ def create_soe_inject_identity_tool(
9
+ execution_id: str,
10
+ backends,
11
+ tools_registry: dict = None,
12
+ ) -> Callable:
13
+ """
14
+ Factory function to create soe_inject_identity tool.
15
+
16
+ Args:
17
+ execution_id: ID to access identity data via backends
18
+ backends: Backend services to fetch/update identities
19
+ tools_registry: Optional registry of available tools (unused by this tool)
20
+
21
+ Returns:
22
+ Configured soe_inject_identity function that can add/update identities
23
+ """
24
+
25
+ def soe_inject_identity(identity_name: str, system_prompt: str) -> Dict[str, Any]:
26
+ """
27
+ Add or update an identity definition.
28
+
29
+ Args:
30
+ identity_name: Name/key for the identity
31
+ system_prompt: The system prompt text for this identity
32
+
33
+ Returns:
34
+ Success confirmation with identity info and action taken
35
+ """
36
+ identities = backends.identity.get_identities(execution_id)
37
+
38
+ if identities is None:
39
+ identities = {}
40
+
41
+ action = "updated" if identity_name in identities else "created"
42
+
43
+ identities[identity_name] = system_prompt
44
+ backends.identity.save_identities(execution_id, identities)
45
+
46
+ register_event(
47
+ backends,
48
+ execution_id,
49
+ EventTypes.NODE_EXECUTION,
50
+ {
51
+ "tool": "soe_inject_identity",
52
+ "identity_name": identity_name,
53
+ "action": action,
54
+ },
55
+ )
56
+
57
+ return {
58
+ "success": True,
59
+ "identity_name": identity_name,
60
+ "action": action,
61
+ "message": f"Successfully {action} identity '{identity_name}'",
62
+ }
63
+
64
+ return soe_inject_identity
@@ -0,0 +1,86 @@
1
+ """Built-in node configuration injection tool."""
2
+
3
+ import json
4
+ from typing import Dict, Any, Callable
5
+ from ..types import EventTypes
6
+ from ..lib.register_event import register_event
7
+ from ..lib.yaml_parser import parse_yaml
8
+
9
+
10
+ def create_soe_inject_node_tool(
11
+ execution_id: str,
12
+ backends,
13
+ tools_registry: dict = None,
14
+ ) -> Callable:
15
+ """
16
+ Factory function to create soe_inject_node tool with workflow access
17
+
18
+ Args:
19
+ execution_id: ID to access workflow data via backends
20
+ backends: Backend services to fetch/update workflows
21
+ tools_registry: Optional registry of available tools (unused by this tool)
22
+
23
+ Returns:
24
+ Configured soe_inject_node function that can inject node config into workflows
25
+ """
26
+
27
+ def soe_soe_inject_node(
28
+ workflow_name: str, node_name: str, node_config_data: str
29
+ ) -> Dict[str, Any]:
30
+ """
31
+ Built-in tool: Inject a node configuration into an existing workflow
32
+
33
+ Args:
34
+ workflow_name: Name of the workflow to modify
35
+ node_name: Name of the node to inject
36
+ node_config_data: YAML or JSON string containing the node configuration
37
+
38
+ Returns:
39
+ Success confirmation with injected node info
40
+ """
41
+
42
+ # Get current workflows registry and validate workflow exists
43
+ workflows_registry = backends.workflow.get_workflows_registry(execution_id)
44
+
45
+ if workflow_name not in workflows_registry:
46
+ raise ValueError(
47
+ f"Workflow '{workflow_name}' not found in workflows registry"
48
+ )
49
+
50
+ # Parse the node configuration data (prefer JSON, fallback to YAML)
51
+ node_config = None
52
+
53
+ try:
54
+ node_config = json.loads(node_config_data)
55
+ except json.JSONDecodeError:
56
+ node_config = parse_yaml(node_config_data)
57
+
58
+ if not isinstance(node_config, dict):
59
+ raise ValueError("Node configuration must be a dictionary/object")
60
+
61
+ # Inject the node configuration into the workflow
62
+ target_workflow = workflows_registry[workflow_name]
63
+ target_workflow[node_name] = node_config
64
+
65
+ # Save the updated workflows registry back
66
+ backends.workflow.save_workflows_registry(execution_id, workflows_registry)
67
+
68
+ register_event(
69
+ backends,
70
+ execution_id,
71
+ EventTypes.NODE_EXECUTION,
72
+ {
73
+ "tool": "soe_inject_node",
74
+ "workflow_name": workflow_name,
75
+ "node_name": node_name,
76
+ },
77
+ )
78
+
79
+ return {
80
+ "injected": True,
81
+ "workflow_name": workflow_name,
82
+ "node_name": node_name,
83
+ "message": f"Successfully injected node '{node_name}' into workflow '{workflow_name}'",
84
+ }
85
+
86
+ return soe_soe_inject_node
@@ -0,0 +1,105 @@
1
+ """Built-in workflow injection tool."""
2
+
3
+ import json
4
+ from typing import Dict, Any, Callable
5
+ from ..types import EventTypes
6
+ from ..lib.register_event import register_event
7
+ from ..lib.yaml_parser import parse_yaml
8
+
9
+
10
+ def create_soe_inject_workflow_tool(
11
+ execution_id: str,
12
+ backends,
13
+ tools_registry: dict = None,
14
+ ) -> Callable:
15
+ """
16
+ Factory function to create soe_inject_workflow tool with workflow access
17
+
18
+ Args:
19
+ execution_id: ID to access workflow data via backends
20
+ backends: Backend services to fetch/update workflows
21
+ tools_registry: Optional registry of available tools (unused by this tool)
22
+
23
+ Returns:
24
+ Configured soe_inject_workflow function that can inject new workflows
25
+ """
26
+
27
+ def soe_inject_workflow(workflow_name: str, workflow_data: str) -> Dict[str, Any]:
28
+ """
29
+ Built-in tool: Inject a new workflow into the global workflows configuration
30
+
31
+ Args:
32
+ workflow_name: Name of the new workflow to inject
33
+ workflow_data: JSON or YAML string containing the workflow definition
34
+
35
+ Returns:
36
+ Success confirmation with injected workflow info
37
+ """
38
+
39
+ # Parse the workflow definition (prefer JSON, fallback to YAML)
40
+ parsed_workflow = None
41
+
42
+ try:
43
+ parsed_workflow = json.loads(workflow_data)
44
+ except json.JSONDecodeError:
45
+ parsed_workflow = parse_yaml(workflow_data)
46
+
47
+ if not isinstance(parsed_workflow, dict):
48
+ raise ValueError("Workflow data must be a dictionary/object")
49
+
50
+ # Determine the workflow definition to inject
51
+ workflow_definition = None
52
+
53
+ # If workflow_name is specified in the parsed data, use that specific workflow
54
+ if workflow_name in parsed_workflow:
55
+ workflow_definition = parsed_workflow[workflow_name]
56
+ else:
57
+ # Check if all keys in parsed_workflow look like node names (have node_type)
58
+ all_nodes = True
59
+ for _, value in parsed_workflow.items():
60
+ if not isinstance(value, dict) or "node_type" not in value:
61
+ all_nodes = False
62
+ break
63
+
64
+ if all_nodes:
65
+ # All top-level keys are nodes, use the entire structure as the workflow
66
+ workflow_definition = parsed_workflow
67
+ elif len(parsed_workflow) == 1:
68
+ # Single non-node entry, assume it's a workflow container
69
+ first_workflow_key = list(parsed_workflow.keys())[0]
70
+ workflow_definition = parsed_workflow[first_workflow_key]
71
+ else:
72
+ # Multiple entries, assume entire structure is the workflow
73
+ workflow_definition = parsed_workflow
74
+
75
+ if not workflow_definition:
76
+ raise ValueError(f"No workflow definition found for injection")
77
+
78
+ # Validate the workflow before injecting
79
+ from ..validation.config import validate_workflow
80
+ validate_workflow(workflow_name, workflow_definition)
81
+
82
+ # Get current workflows registry via backends and inject new workflow
83
+ workflows_registry = backends.workflow.get_workflows_registry(execution_id)
84
+ workflows_registry[workflow_name] = workflow_definition
85
+
86
+ # Save the updated workflows registry back
87
+ backends.workflow.save_workflows_registry(execution_id, workflows_registry)
88
+
89
+ register_event(
90
+ backends,
91
+ execution_id,
92
+ EventTypes.NODE_EXECUTION,
93
+ {
94
+ "tool": "soe_inject_workflow",
95
+ "workflow_name": workflow_name,
96
+ },
97
+ )
98
+
99
+ return {
100
+ "injected": True,
101
+ "workflow_name": workflow_name,
102
+ "message": f"Successfully injected workflow '{workflow_name}'",
103
+ }
104
+
105
+ return soe_inject_workflow
@@ -0,0 +1,73 @@
1
+ """
2
+ Built-in tool: list_contexts
3
+ Allows agents to list available execution contexts.
4
+ """
5
+
6
+ from typing import List, Dict, Any
7
+ import os
8
+ import json
9
+
10
+
11
+ def create_soe_list_contexts_tool(backends, execution_id: str, tools_registry=None):
12
+ """
13
+ Factory that creates a list_contexts tool bound to the current execution.
14
+
15
+ Args:
16
+ backends: Backend instances (needs context backend)
17
+ execution_id: Current execution ID
18
+ tools_registry: Tool registry (unused, for interface compatibility)
19
+
20
+ Returns:
21
+ Configured tool function
22
+ """
23
+
24
+ def list_contexts(include_current: bool = True) -> Dict[str, Any]:
25
+ """
26
+ List available execution contexts.
27
+
28
+ Args:
29
+ include_current: Whether to include current execution in list
30
+
31
+ Returns:
32
+ Dict with current_execution_id and list of context summaries
33
+ """
34
+ result = {
35
+ "current_execution_id": execution_id,
36
+ "contexts": []
37
+ }
38
+
39
+ # Get context storage directory from backend
40
+ storage_dir = getattr(backends.context, 'storage_dir', None)
41
+ if not storage_dir or not os.path.exists(storage_dir):
42
+ return result
43
+
44
+ for filename in os.listdir(storage_dir):
45
+ if not filename.endswith('.json'):
46
+ continue
47
+
48
+ ctx_id = filename.replace('.json', '')
49
+
50
+ if not include_current and ctx_id == execution_id:
51
+ continue
52
+
53
+ # Read minimal info from each context
54
+ filepath = os.path.join(storage_dir, filename)
55
+ try:
56
+ with open(filepath, 'r') as f:
57
+ ctx = json.load(f)
58
+
59
+ # Get summary info
60
+ ops = ctx.get("__operational__", {})
61
+ result["contexts"].append({
62
+ "execution_id": ctx_id,
63
+ "is_current": ctx_id == execution_id,
64
+ "user_request": ctx.get("user_request", [])[-1] if ctx.get("user_request") else None,
65
+ "signals": ops.get("signals", [])[-5:], # Last 5 signals
66
+ "node_count": sum(ops.get("nodes", {}).values()),
67
+ })
68
+ except Exception:
69
+ continue
70
+
71
+ return result
72
+
73
+ return list_contexts
@@ -0,0 +1,61 @@
1
+ """Built-in context schema field removal tool."""
2
+
3
+ from typing import Dict, Any, Callable
4
+ from ..types import EventTypes
5
+ from ..lib.register_event import register_event
6
+
7
+
8
+ def create_soe_remove_context_schema_field_tool(
9
+ execution_id: str,
10
+ backends,
11
+ tools_registry: dict = None,
12
+ ) -> Callable:
13
+ """
14
+ Factory function to create soe_remove_context_schema_field tool.
15
+
16
+ Args:
17
+ execution_id: ID to access context schema data via backends
18
+ backends: Backend services to fetch/update context schema
19
+ tools_registry: Optional registry of available tools (unused by this tool)
20
+
21
+ Returns:
22
+ Configured soe_remove_context_schema_field function
23
+ """
24
+
25
+ def soe_remove_context_schema_field(field_name: str) -> Dict[str, Any]:
26
+ """
27
+ Remove a field from the context schema.
28
+
29
+ Args:
30
+ field_name: Name of the field to remove
31
+
32
+ Returns:
33
+ Success confirmation with removed field info
34
+ """
35
+ schema = backends.context_schema.get_context_schema(execution_id)
36
+
37
+ if schema is None or field_name not in schema:
38
+ raise ValueError(
39
+ f"Field '{field_name}' not found in context schema"
40
+ )
41
+
42
+ del schema[field_name]
43
+ backends.context_schema.save_context_schema(execution_id, schema)
44
+
45
+ register_event(
46
+ backends,
47
+ execution_id,
48
+ EventTypes.NODE_EXECUTION,
49
+ {
50
+ "tool": "soe_remove_context_schema_field",
51
+ "field_name": field_name,
52
+ },
53
+ )
54
+
55
+ return {
56
+ "removed": True,
57
+ "field_name": field_name,
58
+ "message": f"Successfully removed field '{field_name}' from context schema",
59
+ }
60
+
61
+ return soe_remove_context_schema_field
@@ -0,0 +1,61 @@
1
+ """Built-in identity removal tool."""
2
+
3
+ from typing import Dict, Any, Callable
4
+ from ..types import EventTypes
5
+ from ..lib.register_event import register_event
6
+
7
+
8
+ def create_soe_remove_identity_tool(
9
+ execution_id: str,
10
+ backends,
11
+ tools_registry: dict = None,
12
+ ) -> Callable:
13
+ """
14
+ Factory function to create soe_remove_identity tool.
15
+
16
+ Args:
17
+ execution_id: ID to access identity data via backends
18
+ backends: Backend services to fetch/update identities
19
+ tools_registry: Optional registry of available tools (unused by this tool)
20
+
21
+ Returns:
22
+ Configured soe_remove_identity function that can remove identities
23
+ """
24
+
25
+ def soe_remove_identity(identity_name: str) -> Dict[str, Any]:
26
+ """
27
+ Remove an identity definition.
28
+
29
+ Args:
30
+ identity_name: Name of the identity to remove
31
+
32
+ Returns:
33
+ Success confirmation with removed identity info
34
+ """
35
+ identities = backends.identity.get_identities(execution_id)
36
+
37
+ if identities is None or identity_name not in identities:
38
+ raise ValueError(
39
+ f"Identity '{identity_name}' not found"
40
+ )
41
+
42
+ del identities[identity_name]
43
+ backends.identity.save_identities(execution_id, identities)
44
+
45
+ register_event(
46
+ backends,
47
+ execution_id,
48
+ EventTypes.NODE_EXECUTION,
49
+ {
50
+ "tool": "soe_remove_identity",
51
+ "identity_name": identity_name,
52
+ },
53
+ )
54
+
55
+ return {
56
+ "removed": True,
57
+ "identity_name": identity_name,
58
+ "message": f"Successfully removed identity '{identity_name}'",
59
+ }
60
+
61
+ return soe_remove_identity
@@ -0,0 +1,72 @@
1
+ """Built-in node removal tool."""
2
+
3
+ from typing import Dict, Any, Callable
4
+ from ..types import EventTypes
5
+ from ..lib.register_event import register_event
6
+
7
+
8
+ def create_soe_remove_node_tool(
9
+ execution_id: str,
10
+ backends,
11
+ tools_registry: dict = None,
12
+ ) -> Callable:
13
+ """
14
+ Factory function to create soe_remove_node tool with workflow access
15
+
16
+ Args:
17
+ execution_id: ID to access workflow data via backends
18
+ backends: Backend services to fetch/update workflows
19
+ tools_registry: Optional registry of available tools (unused by this tool)
20
+
21
+ Returns:
22
+ Configured soe_remove_node function that can remove nodes from workflows
23
+ """
24
+
25
+ def soe_remove_node(workflow_name: str, node_name: str) -> Dict[str, Any]:
26
+ """
27
+ Built-in tool: Remove a node from an existing workflow
28
+
29
+ Args:
30
+ workflow_name: Name of the workflow to modify
31
+ node_name: Name of the node to remove
32
+
33
+ Returns:
34
+ Success confirmation with removed node info
35
+ """
36
+ workflows_registry = backends.workflow.get_workflows_registry(execution_id)
37
+
38
+ if workflow_name not in workflows_registry:
39
+ raise ValueError(
40
+ f"Workflow '{workflow_name}' not found in workflows registry"
41
+ )
42
+
43
+ target_workflow = workflows_registry[workflow_name]
44
+
45
+ if node_name not in target_workflow:
46
+ raise ValueError(
47
+ f"Node '{node_name}' not found in workflow '{workflow_name}'"
48
+ )
49
+
50
+ del target_workflow[node_name]
51
+
52
+ backends.workflow.save_workflows_registry(execution_id, workflows_registry)
53
+
54
+ register_event(
55
+ backends,
56
+ execution_id,
57
+ EventTypes.NODE_EXECUTION,
58
+ {
59
+ "tool": "soe_remove_node",
60
+ "workflow_name": workflow_name,
61
+ "node_name": node_name,
62
+ },
63
+ )
64
+
65
+ return {
66
+ "removed": True,
67
+ "workflow_name": workflow_name,
68
+ "node_name": node_name,
69
+ "message": f"Successfully removed node '{node_name}' from workflow '{workflow_name}'",
70
+ }
71
+
72
+ return soe_remove_node
@@ -0,0 +1,62 @@
1
+ """Built-in workflow removal tool."""
2
+
3
+ from typing import Dict, Any, Callable
4
+ from ..types import EventTypes
5
+ from ..lib.register_event import register_event
6
+
7
+
8
+ def create_soe_remove_workflow_tool(
9
+ execution_id: str,
10
+ backends,
11
+ tools_registry: dict = None,
12
+ ) -> Callable:
13
+ """
14
+ Factory function to create soe_remove_workflow tool with workflow access
15
+
16
+ Args:
17
+ execution_id: ID to access workflow data via backends
18
+ backends: Backend services to fetch/update workflows
19
+ tools_registry: Optional registry of available tools (unused by this tool)
20
+
21
+ Returns:
22
+ Configured soe_remove_workflow function that can remove workflows
23
+ """
24
+
25
+ def soe_remove_workflow(workflow_name: str) -> Dict[str, Any]:
26
+ """
27
+ Built-in tool: Remove a workflow from the global workflows configuration
28
+
29
+ Args:
30
+ workflow_name: Name of the workflow to remove
31
+
32
+ Returns:
33
+ Success confirmation with removed workflow info
34
+ """
35
+ workflows_registry = backends.workflow.get_workflows_registry(execution_id)
36
+
37
+ if workflow_name not in workflows_registry:
38
+ raise ValueError(
39
+ f"Workflow '{workflow_name}' not found in workflows registry"
40
+ )
41
+
42
+ del workflows_registry[workflow_name]
43
+
44
+ backends.workflow.save_workflows_registry(execution_id, workflows_registry)
45
+
46
+ register_event(
47
+ backends,
48
+ execution_id,
49
+ EventTypes.NODE_EXECUTION,
50
+ {
51
+ "tool": "soe_remove_workflow",
52
+ "workflow_name": workflow_name,
53
+ },
54
+ )
55
+
56
+ return {
57
+ "removed": True,
58
+ "workflow_name": workflow_name,
59
+ "message": f"Successfully removed workflow '{workflow_name}'",
60
+ }
61
+
62
+ return soe_remove_workflow
@@ -0,0 +1,54 @@
1
+ """
2
+ Built-in tool: update_context
3
+ Allows agents to write context fields dynamically.
4
+ """
5
+
6
+ from typing import Any, Dict
7
+
8
+
9
+ def create_soe_update_context_tool(backends, execution_id: str, tools_registry=None):
10
+ """
11
+ Factory that creates an update_context tool bound to the current execution.
12
+
13
+ Args:
14
+ backends: Backend instances (needs context backend)
15
+ execution_id: Current execution ID
16
+ tools_registry: Tool registry (unused, for interface compatibility)
17
+
18
+ Returns:
19
+ Configured tool function
20
+ """
21
+
22
+ def update_context(updates: Dict[str, Any]) -> Dict[str, str]:
23
+ """
24
+ Update context fields for the current execution.
25
+
26
+ Args:
27
+ updates: Dictionary of field names to values to set
28
+
29
+ Returns:
30
+ Confirmation of updated fields
31
+ """
32
+ if not updates:
33
+ return {"status": "no updates provided"}
34
+
35
+ # Don't allow updating operational fields
36
+ filtered_updates = {
37
+ k: v for k, v in updates.items()
38
+ if not k.startswith("__")
39
+ }
40
+
41
+ if not filtered_updates:
42
+ return {"status": "no valid updates (operational fields cannot be updated)"}
43
+
44
+ # Get current context and update
45
+ context = backends.context.get_context(execution_id)
46
+ context.update(filtered_updates)
47
+ backends.context.save_context(execution_id, context)
48
+
49
+ return {
50
+ "status": "updated",
51
+ "fields": list(filtered_updates.keys())
52
+ }
53
+
54
+ return update_context
soe/docs/_config.yml ADDED
@@ -0,0 +1,10 @@
1
+ title: SOE - Signal-driven Orchestration Engine
2
+ description: Infrastructure-agnostic AI workflow orchestration
3
+ theme: jekyll-theme-minimal
4
+ markdown: GFM
5
+ highlighter: rouge
6
+
7
+ # Navigation structure
8
+ header_pages:
9
+ - index.md
10
+ - guide_00_getting_started.md