codemie-sdk-python 0.1.684__tar.gz → 0.1.686__tar.gz
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.
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/PKG-INFO +313 -19
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/README.md +311 -18
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/pyproject.toml +2 -2
- codemie_sdk_python-0.1.686/src/codemie_sdk/builders/workflow/__init__.py +53 -0
- codemie_sdk_python-0.1.686/src/codemie_sdk/builders/workflow/builder.py +383 -0
- codemie_sdk_python-0.1.686/src/codemie_sdk/builders/workflow/definition.py +389 -0
- codemie_sdk_python-0.1.686/src/codemie_sdk/builders/workflow/publish.py +189 -0
- codemie_sdk_python-0.1.686/src/codemie_sdk/models/__init__.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/__init__.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/auth/__init__.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/auth/credentials.py +0 -0
- {codemie_sdk_python-0.1.684/src/codemie_sdk/models → codemie_sdk_python-0.1.686/src/codemie_sdk/builders}/__init__.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/client/__init__.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/client/client.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/exceptions.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/a2a.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/activity_event.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/admin.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/analytics.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/assistant.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/categories.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/common.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/conversation.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/cost_center.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/datasource.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/errors.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/file_operation.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/guardrails.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/integration.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/llm.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/mcp_config.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/mermaid.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/project.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/skill.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/task.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/user.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/vendor_assistant.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/vendor_guardrail.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/vendor_knowledgebase.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/vendor_runtime.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/vendor_workflow.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/workflow.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/workflow_execution_payload.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/workflow_state.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/workflow_thoughts.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/models/workflow_transition.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/a2a.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/activity_event.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/admin.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/analytics.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/assistant.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/categories.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/codemie_guardrails.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/conversation.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/cost_center.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/customer_config_service.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/datasource.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/dynamic_config.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/files.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/integration.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/llm.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/mcp_configs.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/mermaid.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/project.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/project_budget_groups.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/skill.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/task.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/user.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/vendor_assistant.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/vendor_guardrail.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/vendor_knowledgebase.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/vendor_runtime.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/vendor_workflow.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/webhook.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/workflow.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/workflow_execution.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/services/workflow_execution_state.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/utils/__init__.py +0 -0
- {codemie_sdk_python-0.1.684 → codemie_sdk_python-0.1.686}/src/codemie_sdk/utils/http.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: codemie-sdk-python
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.686
|
|
4
4
|
Summary: CodeMie SDK for Python
|
|
5
5
|
Author: Vadym Vlasenko
|
|
6
6
|
Author-email: vadym_vlasenko@epam.com
|
|
@@ -8,6 +8,7 @@ Requires-Python: >=3.12,<4.0
|
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
9
|
Classifier: Programming Language :: Python :: 3.12
|
|
10
10
|
Requires-Dist: pydantic (>=2.12.2,<3.0.0)
|
|
11
|
+
Requires-Dist: pyyaml (>=6.0.2,<7.0.0)
|
|
11
12
|
Requires-Dist: requests (>=2.31.0,<3.0.0)
|
|
12
13
|
Description-Content-Type: text/markdown
|
|
13
14
|
|
|
@@ -40,6 +41,8 @@ Python SDK for CodeMie services. This SDK provides a comprehensive interface to
|
|
|
40
41
|
- [Core Methods](#core-methods-3)
|
|
41
42
|
- [Workflow Execution](#workflow-execution)
|
|
42
43
|
- [Workflow Configuration](#workflow-configuration)
|
|
44
|
+
- [Workflow Builder](#workflow-builder)
|
|
45
|
+
- [Workflow Node Types](#workflow-node-types)
|
|
43
46
|
- [Best Practices](#best-practices)
|
|
44
47
|
- [Error Handling](#error-handling)
|
|
45
48
|
- [Workflow Status Monitoring](#workflow-status-monitoring)
|
|
@@ -792,29 +795,320 @@ def verify_workflow_execution(execution_service, execution_id):
|
|
|
792
795
|
|
|
793
796
|
Workflows support various configuration options:
|
|
794
797
|
|
|
795
|
-
1. **Modes
|
|
796
|
-
- `SEQUENTIAL`:
|
|
797
|
-
- `
|
|
798
|
+
1. **Modes** (`WorkflowMode`):
|
|
799
|
+
- `SEQUENTIAL`: states run one after another, following each state's `next`
|
|
800
|
+
- `AUTONOMOUS`: the platform's older mode, deprecated on the backend
|
|
798
801
|
|
|
799
802
|
2. **YAML Configuration**:
|
|
803
|
+
|
|
804
|
+
The `yaml_config` you pass to `WorkflowCreateRequest` describes the workflow's assistants and
|
|
805
|
+
states. This one has a single assistant that reviews a pull request:
|
|
800
806
|
```yaml
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
807
|
+
assistants:
|
|
808
|
+
- id: reviewer
|
|
809
|
+
model: gpt-4.1-mini
|
|
810
|
+
system_prompt: You review pull requests and list the problems you find.
|
|
811
|
+
|
|
812
|
+
states:
|
|
813
|
+
- id: review
|
|
814
|
+
assistant_id: reviewer
|
|
815
|
+
task: Review the pull request described in {{ user_input }}
|
|
816
|
+
next:
|
|
817
|
+
state_id: end
|
|
818
|
+
```
|
|
819
|
+
Prefer Python over YAML? [Workflow Builder](#workflow-builder) produces this same config, and
|
|
820
|
+
[Workflow Node Types](#workflow-node-types) shows how to add tools, custom and transform nodes,
|
|
821
|
+
and sub-workflows.
|
|
822
|
+
|
|
823
|
+
#### Workflow Builder
|
|
824
|
+
|
|
825
|
+
Writing a workflow by hand means writing YAML and finding out it's wrong only when the backend
|
|
826
|
+
rejects it. `WorkflowBuilder` lets you build the same workflow in plain Python instead, with
|
|
827
|
+
autocomplete and local validation for the fields the builder itself checks (not a full mirror of
|
|
828
|
+
the backend's schema — the backend remains the final check). Every method call gives you back a
|
|
829
|
+
new builder, so it's safe to branch off and customize each copy differently without stepping on
|
|
830
|
+
the others.
|
|
831
|
+
|
|
832
|
+
1. **Build a workflow**
|
|
833
|
+
```python
|
|
834
|
+
from codemie_sdk.builders.workflow import WorkflowBuilder
|
|
835
|
+
from codemie_sdk.builders.workflow.definition import WorkflowNextState
|
|
836
|
+
from codemie_sdk.models.workflow import WorkflowMode
|
|
837
|
+
|
|
838
|
+
builder = (
|
|
839
|
+
WorkflowBuilder("release-notes")
|
|
840
|
+
.with_description("Generate release notes from merged PRs")
|
|
841
|
+
.with_mode(WorkflowMode.SEQUENTIAL)
|
|
842
|
+
.add_assistant("parser", system_prompt="Extract structured PR data.")
|
|
843
|
+
.add_assistant("writer", assistant_id="a1b2c3d4-...") # an existing assistant, by id
|
|
844
|
+
.add_state("parse", "parser", "Extract merged PRs from {{ user_input }}", WorkflowNextState(state_id="draft"))
|
|
845
|
+
.add_state("draft", "writer", "Write the release notes", WorkflowNextState())
|
|
846
|
+
)
|
|
847
|
+
|
|
848
|
+
definition = builder.render()
|
|
849
|
+
yaml_config = definition.to_yaml_config()
|
|
850
|
+
```
|
|
851
|
+
|
|
852
|
+
2. **Reference an assistant by name instead of id**
|
|
853
|
+
```python
|
|
854
|
+
builder_with_ref = builder.add_assistant_ref("reviewer", assistant_name="Release Notes Reviewer")
|
|
855
|
+
|
|
856
|
+
# Works once you tell it how to look the name up:
|
|
857
|
+
builder_with_ref.render().to_yaml_config(resolve_assistant_name=lambda name: my_lookup(name))
|
|
858
|
+
|
|
859
|
+
# Skip the resolver and it just tells you which name it couldn't find, instead of guessing.
|
|
860
|
+
builder_with_ref.render().to_yaml_config() # raises: unresolved assistant reference: 'Release Notes Reviewer'
|
|
861
|
+
```
|
|
862
|
+
|
|
863
|
+
3. **Branches, loops, retries, and human checkpoints**
|
|
864
|
+
```python
|
|
865
|
+
from codemie_sdk.builders.workflow.definition import (
|
|
866
|
+
WorkflowRetryPolicy,
|
|
867
|
+
WorkflowStateCondition,
|
|
868
|
+
WorkflowStateSwitch,
|
|
869
|
+
WorkflowStateSwitchCondition,
|
|
870
|
+
)
|
|
871
|
+
|
|
872
|
+
# Every add_state() call returns a new builder — keep reassigning it, or the
|
|
873
|
+
# call is a no-op and chaining further calls on the old builder re-adds the
|
|
874
|
+
# same id and raises "duplicate state id".
|
|
875
|
+
|
|
876
|
+
# if / else
|
|
877
|
+
builder = builder.add_state("check_count", "writer", "Assemble the notes", WorkflowNextState(
|
|
878
|
+
condition=WorkflowStateCondition(expression="count > 0", then="publish", otherwise="end")
|
|
879
|
+
))
|
|
880
|
+
|
|
881
|
+
# switch / case
|
|
882
|
+
builder = builder.add_state("route", "writer", "Route by language", WorkflowNextState(
|
|
883
|
+
switch=WorkflowStateSwitch(
|
|
884
|
+
cases=[
|
|
885
|
+
WorkflowStateSwitchCondition(condition="language == 'Java'", state_id="java_path"),
|
|
886
|
+
WorkflowStateSwitchCondition(condition="language == 'Python'", state_id="python_path"),
|
|
887
|
+
],
|
|
888
|
+
default="end",
|
|
889
|
+
)
|
|
890
|
+
))
|
|
891
|
+
|
|
892
|
+
# loop over an array, collect the results
|
|
893
|
+
builder = builder.add_state("summarize", "writer", "Write a line for {{ iter_item }}",
|
|
894
|
+
WorkflowNextState(state_id="route", iter_key="prs", output_key="lines"))
|
|
895
|
+
|
|
896
|
+
# retry on failure
|
|
897
|
+
builder = builder.add_state("retry_demo", "writer", "Write the release notes", WorkflowNextState(),
|
|
898
|
+
retry_policy=WorkflowRetryPolicy(initial_interval=1.0, backoff_factor=2.0,
|
|
899
|
+
max_interval=10.0, max_attempts=3))
|
|
900
|
+
|
|
901
|
+
# pause here for a human to review before continuing
|
|
902
|
+
builder = builder.add_state("human_review", "writer", "Assemble the notes", WorkflowNextState(), interrupt_before=True)
|
|
903
|
+
|
|
904
|
+
builder = builder.with_mode(WorkflowMode.AUTONOMOUS)
|
|
816
905
|
```
|
|
817
906
|
|
|
907
|
+
4. **Publish it**
|
|
908
|
+
```python
|
|
909
|
+
# Create a new workflow
|
|
910
|
+
result = builder.publish(client, project="my-project")
|
|
911
|
+
|
|
912
|
+
# Or update one that already exists
|
|
913
|
+
result = builder.publish(client, project="my-project", workflow_id="workflow-id")
|
|
914
|
+
```
|
|
915
|
+
This is just a shortcut for rendering the YAML and calling `client.workflows.create_workflow`/
|
|
916
|
+
`.update` yourself, so nothing about using those directly changes.
|
|
917
|
+
|
|
918
|
+
5. **Using `WorkflowBuilder` with `WorkflowCreateRequest`**
|
|
919
|
+
|
|
920
|
+
If you'd rather build the request yourself instead of publishing right away:
|
|
921
|
+
```python
|
|
922
|
+
from codemie_sdk.models.workflow import WorkflowCreateRequest
|
|
923
|
+
|
|
924
|
+
definition = builder.render()
|
|
925
|
+
request = WorkflowCreateRequest(
|
|
926
|
+
project="my-project",
|
|
927
|
+
name=definition.name,
|
|
928
|
+
description=definition.description,
|
|
929
|
+
yaml_config=definition.to_yaml_config(),
|
|
930
|
+
mode=definition.mode,
|
|
931
|
+
shared=definition.shared,
|
|
932
|
+
icon_url=definition.icon_url,
|
|
933
|
+
)
|
|
934
|
+
```
|
|
935
|
+
|
|
936
|
+
#### Workflow Node Types
|
|
937
|
+
|
|
938
|
+
Every state in a workflow runs one thing: an assistant, a tool, a custom node (such as
|
|
939
|
+
transform), or another workflow. The examples below are independent — each builds its own small
|
|
940
|
+
workflow.
|
|
941
|
+
|
|
942
|
+
**Assistant node**
|
|
943
|
+
|
|
944
|
+
1. **Give it a tool**
|
|
945
|
+
|
|
946
|
+
Tool names are the ones returned by `client.assistants.get_tools()`.
|
|
947
|
+
```python
|
|
948
|
+
from codemie_sdk.builders.workflow import (
|
|
949
|
+
WorkflowAssistantTool,
|
|
950
|
+
WorkflowBuilder,
|
|
951
|
+
WorkflowMCPServer,
|
|
952
|
+
WorkflowNextState,
|
|
953
|
+
)
|
|
954
|
+
|
|
955
|
+
builder = (
|
|
956
|
+
WorkflowBuilder("code-helper")
|
|
957
|
+
.add_assistant(
|
|
958
|
+
"helper",
|
|
959
|
+
system_prompt="You answer questions about the project files.",
|
|
960
|
+
tools=[WorkflowAssistantTool(name="_list_directory")],
|
|
961
|
+
)
|
|
962
|
+
.add_state("ask", "helper", "List what is in the project", WorkflowNextState())
|
|
963
|
+
)
|
|
964
|
+
```
|
|
965
|
+
|
|
966
|
+
2. **Give it an external tool**
|
|
967
|
+
|
|
968
|
+
Tools that talk to an outside system need an integration (see [Integration Service](#integration-service)).
|
|
969
|
+
Point to it by alias:
|
|
970
|
+
```python
|
|
971
|
+
builder = (
|
|
972
|
+
WorkflowBuilder("file-reader")
|
|
973
|
+
.add_assistant(
|
|
974
|
+
"reader",
|
|
975
|
+
system_prompt="You read files from the project.",
|
|
976
|
+
tools=[WorkflowAssistantTool(name="_read_file", integration_alias="my-plugin-integration")],
|
|
977
|
+
)
|
|
978
|
+
.add_state("read", "reader", "Read the README", WorkflowNextState())
|
|
979
|
+
)
|
|
980
|
+
```
|
|
981
|
+
|
|
982
|
+
3. **Give it an MCP server**
|
|
983
|
+
```python
|
|
984
|
+
builder = (
|
|
985
|
+
WorkflowBuilder("file-helper")
|
|
986
|
+
.add_assistant(
|
|
987
|
+
"files",
|
|
988
|
+
system_prompt="You manage files in the project folder.",
|
|
989
|
+
mcp_servers=[
|
|
990
|
+
WorkflowMCPServer(
|
|
991
|
+
name="filesystem",
|
|
992
|
+
config={"command": "mcp-server-filesystem", "args": ["/home/codemie"]},
|
|
993
|
+
),
|
|
994
|
+
# or reuse a server from the MCP catalog
|
|
995
|
+
WorkflowMCPServer(name="github", mcp_config_id="your-catalog-config-id"),
|
|
996
|
+
],
|
|
997
|
+
)
|
|
998
|
+
.add_state("tidy", "files", "Tidy up the project folder", WorkflowNextState())
|
|
999
|
+
)
|
|
1000
|
+
```
|
|
1001
|
+
|
|
1002
|
+
**Tool, custom, transform and sub-workflow nodes**
|
|
1003
|
+
|
|
1004
|
+
Tools and custom nodes are declared once and then used by id, the same way an assistant is
|
|
1005
|
+
registered before a state runs it. Naming follows the workflow YAML, so `tool_id` and
|
|
1006
|
+
`custom_node_id` in a state point at the `id` you declared.
|
|
1007
|
+
|
|
1008
|
+
4. **Tool node** — runs a single tool directly, no LLM in between
|
|
1009
|
+
```python
|
|
1010
|
+
builder = (
|
|
1011
|
+
WorkflowBuilder("find-sources")
|
|
1012
|
+
.add_tool(
|
|
1013
|
+
"find_sources",
|
|
1014
|
+
"_search_files_by_regex",
|
|
1015
|
+
integration_alias="my-plugin-integration",
|
|
1016
|
+
)
|
|
1017
|
+
.add_tool_state(
|
|
1018
|
+
"search",
|
|
1019
|
+
"find_sources",
|
|
1020
|
+
WorkflowNextState(state_id="end"),
|
|
1021
|
+
tool_args={"path": "src", "regex": "[.]py$"},
|
|
1022
|
+
)
|
|
1023
|
+
)
|
|
1024
|
+
```
|
|
1025
|
+
A tool that is served by an MCP server takes `mcp_server`:
|
|
1026
|
+
```python
|
|
1027
|
+
builder = WorkflowBuilder("run-commands").add_tool(
|
|
1028
|
+
"run_command",
|
|
1029
|
+
"run_command",
|
|
1030
|
+
mcp_server=WorkflowMCPServer(
|
|
1031
|
+
name="CLI MCP Server",
|
|
1032
|
+
description="Runs shell commands",
|
|
1033
|
+
mcp_connect_url="http://codemie-mcp-connect:3000",
|
|
1034
|
+
config={"command": "uvx", "args": ["cli-mcp-server"]},
|
|
1035
|
+
),
|
|
1036
|
+
)
|
|
1037
|
+
```
|
|
1038
|
+
|
|
1039
|
+
5. **Custom node** — a ready-made processing step from the platform. The first argument is your
|
|
1040
|
+
name for it, the second is the kind of node
|
|
1041
|
+
```python
|
|
1042
|
+
builder = (
|
|
1043
|
+
WorkflowBuilder("review-summary")
|
|
1044
|
+
.add_custom_node(
|
|
1045
|
+
"summary",
|
|
1046
|
+
"state_processor_node",
|
|
1047
|
+
model="gpt-4.1-mini",
|
|
1048
|
+
config={
|
|
1049
|
+
"state_id": "review",
|
|
1050
|
+
"output_template": "{% for item in items %}- {{ item.file_path }}: {{ item.conclusion }}\n{% endfor %}",
|
|
1051
|
+
},
|
|
1052
|
+
)
|
|
1053
|
+
.add_custom_node_state(
|
|
1054
|
+
"summarize",
|
|
1055
|
+
"summary",
|
|
1056
|
+
WorkflowNextState(state_id="end"),
|
|
1057
|
+
task="Summarize the review results",
|
|
1058
|
+
)
|
|
1059
|
+
)
|
|
1060
|
+
```
|
|
1061
|
+
|
|
1062
|
+
6. **Transform node** — reshapes data without an LLM. It's a custom node, so you run it with
|
|
1063
|
+
`add_custom_node_state`
|
|
1064
|
+
```python
|
|
1065
|
+
builder = (
|
|
1066
|
+
WorkflowBuilder("shape-pr")
|
|
1067
|
+
.add_transform_node(
|
|
1068
|
+
"shape_pr",
|
|
1069
|
+
mappings=[
|
|
1070
|
+
{"output_field": "title", "type": "extract", "source_path": "pull_request.title"},
|
|
1071
|
+
{
|
|
1072
|
+
"output_field": "summary",
|
|
1073
|
+
"type": "template",
|
|
1074
|
+
"template": "PR #{{ number }} by @{{ pull_request.user.login }}",
|
|
1075
|
+
},
|
|
1076
|
+
{
|
|
1077
|
+
"output_field": "actionable",
|
|
1078
|
+
"type": "condition",
|
|
1079
|
+
"condition": "action in ['opened', 'reopened']",
|
|
1080
|
+
"then_value": True,
|
|
1081
|
+
"else_value": False,
|
|
1082
|
+
},
|
|
1083
|
+
],
|
|
1084
|
+
on_error="fail",
|
|
1085
|
+
)
|
|
1086
|
+
.add_custom_node_state(
|
|
1087
|
+
"shape_event",
|
|
1088
|
+
"shape_pr",
|
|
1089
|
+
WorkflowNextState(state_id="end", output_key="pr"),
|
|
1090
|
+
task="Shape the PR event",
|
|
1091
|
+
)
|
|
1092
|
+
)
|
|
1093
|
+
```
|
|
1094
|
+
Other mapping types are `constant`, `script` and `array_map`. `on_error` can be `fail`, `skip`,
|
|
1095
|
+
`default` (use together with `default_output`) or `partial`.
|
|
1096
|
+
|
|
1097
|
+
7. **Sub-workflow node** — runs another workflow and waits for it
|
|
1098
|
+
```python
|
|
1099
|
+
builder = WorkflowBuilder("review-pipeline").add_sub_workflow_state(
|
|
1100
|
+
"run_review",
|
|
1101
|
+
"your-workflow-id",
|
|
1102
|
+
WorkflowNextState(state_id="end"),
|
|
1103
|
+
)
|
|
1104
|
+
```
|
|
1105
|
+
The sub-workflow gets the previous state's output as its input, and its last output becomes this
|
|
1106
|
+
state's output. The `subWorkflow` feature has to be enabled on your CodeMie instance, and
|
|
1107
|
+
workflows can only be nested up to a limit.
|
|
1108
|
+
|
|
1109
|
+
All of these chain on the same builder, so one workflow can mix assistants, tools, custom
|
|
1110
|
+
nodes and sub-workflows.
|
|
1111
|
+
|
|
818
1112
|
#### Best Practices
|
|
819
1113
|
|
|
820
1114
|
1. **Workflow Design**:
|