|
| 1 | +# Semantic Workflow Profile |
| 2 | + |
| 3 | +This page explains what the built-in `semantic-workflow` profile is, why it |
| 4 | +exists, and when you should use it. |
| 5 | + |
| 6 | +## What It Is |
| 7 | + |
| 8 | +`semantic-workflow` is a **tool discovery profile** for native ZCP clients. |
| 9 | + |
| 10 | +Instead of always returning the full primitive tool registry, a client can ask |
| 11 | +the server for a smaller registry that contains only workflow-level tools: |
| 12 | + |
| 13 | +```python |
| 14 | +from zcp import SemanticWorkflowProfile |
| 15 | + |
| 16 | +profile = SemanticWorkflowProfile() |
| 17 | +tools = await client.list_tools(**profile.as_list_tools_params()) |
| 18 | +``` |
| 19 | + |
| 20 | +In raw form, this is the same as: |
| 21 | + |
| 22 | +```python |
| 23 | +tools = await client.list_tools(profile="semantic-workflow") |
| 24 | +``` |
| 25 | + |
| 26 | +When the server publishes tools tagged with `_meta.groups` that include |
| 27 | +`workflow`, the returned registry is narrowed to that workflow subset. |
| 28 | + |
| 29 | +## Why It Exists |
| 30 | + |
| 31 | +MCP-compatible primitive tools are good for interoperability, but they are not |
| 32 | +always good planning units for model-driven execution. |
| 33 | + |
| 34 | +For example, a spreadsheet server may expose primitive tools such as: |
| 35 | + |
| 36 | +- `write_data_to_excel` |
| 37 | +- `format_range` |
| 38 | +- `merge_cells` |
| 39 | +- `read_data_from_excel` |
| 40 | + |
| 41 | +Those are fine for compatibility, but a native client planning a larger task |
| 42 | +often does better when it sees higher-level tools such as: |
| 43 | + |
| 44 | +- `build_sales_report_workflow` |
| 45 | +- `repair_board_packet_workflow` |
| 46 | +- `close_month_end_workflow` |
| 47 | + |
| 48 | +The `semantic-workflow` profile exists to let one server keep both surfaces: |
| 49 | + |
| 50 | +- a broad MCP-compatible primitive tool surface |
| 51 | +- a narrower native planning surface |
| 52 | + |
| 53 | +## What The Profile Actually Does |
| 54 | + |
| 55 | +The profile does **not** change the protocol. |
| 56 | + |
| 57 | +It changes which tools are returned by `tools/list`. |
| 58 | + |
| 59 | +The server checks the current tool registry and, when workflow-tagged tools are |
| 60 | +present, returns only that subset for clients asking for |
| 61 | +`profile="semantic-workflow"`. |
| 62 | + |
| 63 | +That means: |
| 64 | + |
| 65 | +- MCP compatibility remains available |
| 66 | +- native ZCP clients get a smaller registry |
| 67 | +- model planning sees fewer low-level operations |
| 68 | +- token usage usually drops because the model needs fewer tool descriptions and |
| 69 | + fewer planning turns |
| 70 | + |
| 71 | +## How The Server Marks Workflow Tools |
| 72 | + |
| 73 | +Workflow tools are ordinary tools with workflow metadata. |
| 74 | + |
| 75 | +Typical pattern: |
| 76 | + |
| 77 | +```python |
| 78 | +@app.tool( |
| 79 | + name="build_sales_report_workflow", |
| 80 | + description="Create a sales summary workbook from raw inputs.", |
| 81 | + input_schema={ |
| 82 | + "type": "object", |
| 83 | + "properties": { |
| 84 | + "workbook_path": {"type": "string"}, |
| 85 | + "rows": {"type": "array"}, |
| 86 | + }, |
| 87 | + "required": ["workbook_path", "rows"], |
| 88 | + "additionalProperties": False, |
| 89 | + }, |
| 90 | + output_mode="scalar", |
| 91 | + inline_ok=True, |
| 92 | + metadata={ |
| 93 | + "_meta": { |
| 94 | + "groups": ["workflow", "reporting"], |
| 95 | + "stages": ["build", "verify"], |
| 96 | + } |
| 97 | + }, |
| 98 | +) |
| 99 | +async def build_sales_report_workflow(workbook_path: str, rows: list[dict]): |
| 100 | + ... |
| 101 | +``` |
| 102 | + |
| 103 | +The key part is: |
| 104 | + |
| 105 | +- `_meta.groups` includes `workflow` |
| 106 | + |
| 107 | +The built-in profile uses that convention as the discovery filter. |
| 108 | + |
| 109 | +## Server Configuration |
| 110 | + |
| 111 | +You can expose the profile by convention and make it the native default: |
| 112 | + |
| 113 | +```python |
| 114 | +from zcp import FastZCP, ToolExposureConfig, ZCPServerConfig |
| 115 | + |
| 116 | +app = FastZCP( |
| 117 | + "Excel Native Server", |
| 118 | + default_tool_profile="semantic-workflow", |
| 119 | +) |
| 120 | + |
| 121 | +config = ZCPServerConfig( |
| 122 | + tool_exposure=ToolExposureConfig( |
| 123 | + default_profile="semantic-workflow", |
| 124 | + ) |
| 125 | +) |
| 126 | +``` |
| 127 | + |
| 128 | +Important fields: |
| 129 | + |
| 130 | +- `FastZCP(default_tool_profile="semantic-workflow")` |
| 131 | +- `ToolExposureConfig(default_profile="semantic-workflow")` |
| 132 | +- `ToolExposureConfig.semantic_group` |
| 133 | +- `ToolExposureConfig.enforce_call_visibility` |
| 134 | + |
| 135 | +The first two define the preferred discovery path. The latter two define how |
| 136 | +strictly the runtime maps profile visibility to callable tools. |
| 137 | + |
| 138 | +## Client Configuration |
| 139 | + |
| 140 | +The explicit client-side form is: |
| 141 | + |
| 142 | +```python |
| 143 | +tools = await client.list_tools(profile="semantic-workflow") |
| 144 | +``` |
| 145 | + |
| 146 | +The convenience wrapper is: |
| 147 | + |
| 148 | +```python |
| 149 | +from zcp import SemanticWorkflowProfile |
| 150 | + |
| 151 | +profile = SemanticWorkflowProfile() |
| 152 | +tools = await client.list_tools(**profile.as_list_tools_params()) |
| 153 | +``` |
| 154 | + |
| 155 | +Use the explicit form when you are wiring a custom planner. Use the wrapper |
| 156 | +when you want the built-in native profile object. |
| 157 | + |
| 158 | +## Relationship To MCP |
| 159 | + |
| 160 | +`semantic-workflow` is a **ZCP-native discovery contract**, not an MCP feature. |
| 161 | + |
| 162 | +That means: |
| 163 | + |
| 164 | +- MCP clients do not need to know about it |
| 165 | +- MCP-compatible endpoints can still expose the primitive registry |
| 166 | +- native ZCP clients can ask for the workflow subset on the same runtime |
| 167 | + |
| 168 | +So the design is: |
| 169 | + |
| 170 | +- **downward compatible** with MCP |
| 171 | +- **more opinionated** for native ZCP planning |
| 172 | + |
| 173 | +## When You Should Use It |
| 174 | + |
| 175 | +Use `semantic-workflow` when all of these are true: |
| 176 | + |
| 177 | +- the server exposes both primitive and higher-level workflow tools |
| 178 | +- the native client is model-driven |
| 179 | +- token efficiency matters |
| 180 | +- you want fewer, more semantic planning steps |
| 181 | + |
| 182 | +Do not rely on it when: |
| 183 | + |
| 184 | +- the server only exposes primitive tools |
| 185 | +- you need exact low-level control of every operation |
| 186 | +- your client is an MCP host that expects the full primitive surface |
| 187 | + |
| 188 | +## How It Differs From Simple Group Filters |
| 189 | + |
| 190 | +ZCP also supports direct filtering parameters such as: |
| 191 | + |
| 192 | +- `groups` |
| 193 | +- `excludeGroups` |
| 194 | +- `stages` |
| 195 | + |
| 196 | +Those are generic filters. |
| 197 | + |
| 198 | +`semantic-workflow` is different because it is a named profile with a stable |
| 199 | +meaning: |
| 200 | + |
| 201 | +- workflow tools first |
| 202 | +- native planning path |
| 203 | +- smaller registry by default |
| 204 | + |
| 205 | +Use raw group filters when you need one-off selection logic. Use the profile |
| 206 | +when you want a consistent native discovery contract. |
| 207 | + |
| 208 | +## Current Runtime Shape |
| 209 | + |
| 210 | +The current built-in implementation lives in the Python SDK: |
| 211 | + |
| 212 | +- [`SemanticWorkflowProfile`](/docs/sdk-api) |
| 213 | +- [`ToolExposureConfig`](/docs/sdk-api) |
| 214 | +- [`FastZCP`](/docs/servers) |
| 215 | +- [`ZCPClientSession.list_tools`](/docs/clients) |
| 216 | + |
| 217 | +The profile name today is: |
| 218 | + |
| 219 | +- `semantic-workflow` |
| 220 | + |
| 221 | +The default semantic group today is: |
| 222 | + |
| 223 | +- `workflow` |
| 224 | + |
| 225 | +Those are conventions, but the server-side config lets you override the group |
| 226 | +name if you need a different internal taxonomy. |
| 227 | + |
| 228 | +## Practical Outcome |
| 229 | + |
| 230 | +In the Excel benchmark suite, this profile is part of the reason native ZCP can |
| 231 | +use semantic workflow tools instead of exposing only MCP-style primitives. |
| 232 | + |
| 233 | +That is what allows the runtime to preserve MCP compatibility while still |
| 234 | +reducing planning turns and token cost for native ZCP clients. |
| 235 | + |
| 236 | +For the benchmark context and current published results, see: |
| 237 | + |
| 238 | +- [Benchmark Methodology](/docs/benchmark-methodology) |
| 239 | +- [Capability Matrix](/docs/capability-matrix) |
| 240 | +- [Client Guide](/docs/clients) |
| 241 | +- [Server Guide](/docs/servers) |
0 commit comments