From 0e4502c62bcac24671a0d31a17d6fc844a17195c Mon Sep 17 00:00:00 2001 From: Kevin Backhouse Date: Wed, 15 Oct 2025 22:12:29 +0100 Subject: [PATCH 1/3] Use filekeys for cross-referencing --- README.md | 80 ++++++++++++++++--- available_tools.py | 22 +++-- main.py | 10 ++- mcp_utils.py | 2 +- personalities/assistant.yaml | 3 +- personalities/c_auditer.yaml | 7 +- personalities/examples/apple_expert.yaml | 3 +- personalities/examples/banana_expert.yaml | 3 +- personalities/examples/echo.yaml | 5 +- .../examples/example_triage_agent.yaml | 3 +- personalities/examples/fruit_expert.yaml | 3 +- personalities/examples/orange_expert.yaml | 3 +- prompts/examples/example_prompt.yaml | 3 +- taskflows/CVE-2023-2283/CVE-2023-2283.yaml | 17 ++-- taskflows/examples/echo.yaml | 7 +- taskflows/examples/example.yaml | 17 ++-- taskflows/examples/example_globals.yaml | 5 +- taskflows/examples/example_inputs.yaml | 5 +- .../example_large_list_result_iter.yaml | 9 ++- taskflows/examples/example_repeat_prompt.yaml | 9 ++- .../examples/example_repeat_prompt_async.yaml | 9 ++- .../example_repeat_prompt_dictionary.yaml | 9 ++- .../examples/example_reusable_prompt.yaml | 7 +- .../examples/example_reusable_taskflows.yaml | 5 +- .../examples/example_triage_taskflow.yaml | 19 ++--- taskflows/examples/single_step_taskflow.yaml | 5 +- toolboxes/codeql.yaml | 3 +- toolboxes/echo.yaml | 3 +- toolboxes/github_official.yaml | 3 +- toolboxes/logbook.yaml | 5 +- toolboxes/memcache.yaml | 5 +- yaml_parser.py | 23 ++---- 32 files changed, 201 insertions(+), 111 deletions(-) diff --git a/README.md b/README.md index 7452f9f..35f5b91 100644 --- a/README.md +++ b/README.md @@ -149,6 +149,11 @@ Example: ```yaml # personalities define the system prompt level directives for this Agent +seclab-taskflow-agent: + version: 1 + filetype: personality + filekey: personalities/examples/echo + personality: | You are a simple echo bot. You use echo tools to echo things. @@ -157,7 +162,7 @@ task: | # personality toolboxes map to mcp servers made available to this Agent toolboxes: - - echo + - toolboxes/echo ``` ## Toolboxes @@ -168,6 +173,11 @@ Example stdio config: ```yaml # stdio mcp server configuration +seclab-taskflow-agent: + version: 1 + filetype: toolbox + filekey: toolboxes/echo + server_params: kind: stdio command: python @@ -184,6 +194,11 @@ A sequence of interdependent tasks performed by a set of Agents. Configured thro Example: ```yaml +seclab-taskflow-agent: + version: 1 + filetype: taskflow + filekey: taskflows/examples/example.yaml + taskflow: - task: # taskflows can optionally choose any of the support CAPI models for a task @@ -194,18 +209,14 @@ taskflow: must_complete: true # taskflows can set a primary (first entry) and handoff (additional entries) agent agents: - - c_auditer - - fruit_expert + - personalities/c_auditer.yaml + - personalities/examples/fruit_expert.yaml user_prompt: | Store an example vulnerable C program that uses `strcpy` in the `vulnerable_c_example` memory key and explain why `strcpy` is insecure in the C programming language. Do this before handing off to any other agent. - Then provide a summary of a high impact CVE ID that involved a `strcpy` - based buffer overflow based on your GHSA knowledge as an additional - example. - Finally, why are apples and oranges healthy to eat? # taskflows can set temporary environment variables, these support the general @@ -217,16 +228,16 @@ taskflow: MEMCACHE_STATE_DIR: "example_taskflow/" MEMCACHE_BACKEND: "dictionary_file" # taskflows can optionally override personality toolboxes, in this example - # kevin normally only has the memcache toolbox, but we extend it here with + # this normally only has the memcache toolbox, but we extend it here with # the GHSA toolbox toolboxes: - - ghsa - - memcache + - toolboxes/memcache.yaml + - toolboxes/codeql.yaml - task: must_complete: true model: gpt-4.1 agents: - - c_auditer + - personalities/c_auditer.yaml user_prompt: | Retrieve C code for security review from the `vulnerable_c_example` memory key and perform a review. @@ -236,13 +247,58 @@ taskflow: MEMCACHE_STATE_DIR: "example_taskflow/" MEMCACHE_BACKEND: "dictionary_file" toolboxes: - - memcache + - toolboxes/memcache.yaml + # headless mode does not prompt for tool call confirms configured for a server + # note: this will auto-allow, if you want control over potentially dangerous + # tool calls, then you should NOT run a task in headless mode (default: false) + headless: true + - task: + # tasks can also run shell scripts that return e.g. json output for repeat prompt iterable + must_complete: true + run: | + echo '["apple", "banana", "orange"]' + - task: + repeat_prompt: true + agents: + - personalities/assistant.yaml + user_prompt: | + What kind of fruit is {{ RESULT }}? ``` Taskflows support [Agent handoffs](https://openai.github.io/openai-agents-python/handoffs/). Handoffs are useful for implementing triage patterns where the primary Agent can decide to handoff a task to any subsequent Agents in the `Agents` list. See the [taskflow examples](taskflows/examples) for other useful Taskflow patterns such as repeatable and asynchronous templated prompts. +## Notes about the yaml syntax + +Every personality, toolbox, and taskflow is defined by a YAML file, which +should always include a header like this: + +``` +seclab-taskflow-agent: + version: 1 + filetype: taskflow + filekey: taskflows/examples/example +``` + +The "filetype" determines whether the file defines a personality, toolbox, or +taskflow. This means that different types of files can be stored in the same directory. + +The "filekey" is a unique name for the file. It is used to allow +cross-referencing between files. For example, a taskflow can reference +a personality by its filekey. Because filekeys are used for +cross-referencing (rather than file paths), it means that you can move +a file to a different directory without breaking the links. This also +means that you can easily import new files by dropping them into a sub-directory. +We recommend including something like your +GitHub "username/reponame" in your filekeys to make them globably unique. + +The "version" number in the header should always be 1. It means that the +file uses version 1 of the seclab-taskflow-agent syntax. If we ever need +to make a major change to the syntax, then we'll update the version number. +This will hopefully enable us to make changes without breaking backwards +compatibility. + ## License This project is licensed under the terms of the MIT open source license. Please refer to the [LICENSE](./LICENSE) file for the full terms. diff --git a/available_tools.py b/available_tools.py index e2c87c5..273ed34 100644 --- a/available_tools.py +++ b/available_tools.py @@ -3,9 +3,18 @@ class VersionException(Exception): pass +class FileIDException(Exception): + pass + class FileTypeException(Exception): pass +def add_yaml_to_dict(table, key, yaml): + """Add the yaml to the table, but raise an error if the id isn't unique """ + if key in table: + raise FileIDException(str(key)) + table.update({key: yaml}) + class AvailableTools: """ This class is used for storing dictionaries of all the available @@ -30,20 +39,23 @@ def __init__(self, yamls: dict): version = header['version'] if version != 1: raise VersionException(str(version)) - filetype = header['type'] + filekey = header['filekey'] + filetype = header['filetype'] if filetype == 'personality': - self.personalities.update({path: yaml}) + add_yaml_to_dict(self.personalities, filekey, yaml) elif filetype == 'taskflow': - self.taskflows.update({path: yaml}) + add_yaml_to_dict(self.taskflows, filekey, yaml) elif filetype == 'prompt': - self.prompts.update({path: yaml}) + add_yaml_to_dict(self.prompts, filekey, yaml) elif filetype == 'toolbox': - self.toolboxes.update({path: yaml}) + add_yaml_to_dict(self.toolboxes, filekey, yaml) else: raise FileTypeException(str(filetype)) except KeyError as err: logging.error(f'{path} does not contain the key {err.args[0]}') except VersionException as err: logging.error(f'{path}: seclab-taskflow-agent version {err.args[0]} is not supported') + except FileIDException as err: + logging.error(f'{path}: file ID {err.args[0]} is not unique') except FileTypeException as err: logging.error(f'{path}: seclab-taskflow-agent file type {err.args[0]} is not supported') diff --git a/main.py b/main.py index fed125a..0d60e16 100644 --- a/main.py +++ b/main.py @@ -10,6 +10,7 @@ import re import json import uuid +import pathlib from agent import DEFAULT_MODEL, TaskRunHooks, TaskAgentHooks #from agents.run import DEFAULT_MAX_TURNS # XXX: this is 10, we need more than that @@ -628,11 +629,12 @@ async def _deploy_task_agents(resolved_agents, prompt): break if __name__ == '__main__': + cwd = pathlib.Path.cwd() available_tools = AvailableTools( - YamlParser('personalities').get_yaml_dict() | - YamlParser('taskflows').get_yaml_dict() | - YamlParser('prompts').get_yaml_dict(dir_namespace=True) | - YamlParser('toolboxes').get_yaml_dict(recurse=True)) + YamlParser(cwd).get_yaml_dict((cwd/'personalities').rglob('*')) | + YamlParser(cwd).get_yaml_dict((cwd/'taskflows').rglob('*')) | + YamlParser(cwd).get_yaml_dict((cwd/'prompts').rglob('*')) | + YamlParser(cwd).get_yaml_dict((cwd/'toolboxes').rglob('*'))) p, t, l, user_prompt, help_msg = parse_prompt_args(available_tools) diff --git a/mcp_utils.py b/mcp_utils.py index dd64909..5fd2187 100644 --- a/mcp_utils.py +++ b/mcp_utils.py @@ -221,7 +221,7 @@ class MCPNamespaceWrap: def __init__(self, confirms, obj): self.confirms = confirms self._obj = obj - self.namespace = f"{obj.name.upper().replace(' ', '_')}_" + self.namespace = f"{obj.name.upper().replace(' ', '_').replace('/','-')}_" def __getattr__(self, name): attr = getattr(self._obj, name) diff --git a/personalities/assistant.yaml b/personalities/assistant.yaml index 3069859..c46b9c9 100644 --- a/personalities/assistant.yaml +++ b/personalities/assistant.yaml @@ -1,6 +1,7 @@ seclab-taskflow-agent: - type: personality version: 1 + filetype: personality + filekey: personalities/assistant.yaml personality: | You are a helpful assistant. diff --git a/personalities/c_auditer.yaml b/personalities/c_auditer.yaml index 3d1f6ba..bb2a4b1 100644 --- a/personalities/c_auditer.yaml +++ b/personalities/c_auditer.yaml @@ -1,6 +1,7 @@ seclab-taskflow-agent: - type: personality version: 1 + filetype: personality + filekey: personalities/c_auditer.yaml personality: | Your name is Ronald. You are a C programming language security expert. @@ -14,5 +15,5 @@ task: | your findings where possible. toolboxes: - - memcache - - codeql + - toolboxes/memcache.yaml + - toolboxes/codeql.yaml diff --git a/personalities/examples/apple_expert.yaml b/personalities/examples/apple_expert.yaml index 84eb1db..fd271e0 100644 --- a/personalities/examples/apple_expert.yaml +++ b/personalities/examples/apple_expert.yaml @@ -1,6 +1,7 @@ seclab-taskflow-agent: - type: personality version: 1 + filetype: personality + filekey: personalities/examples/apple_expert.yaml personality: | You are an apples expert. diff --git a/personalities/examples/banana_expert.yaml b/personalities/examples/banana_expert.yaml index d37f038..5693426 100644 --- a/personalities/examples/banana_expert.yaml +++ b/personalities/examples/banana_expert.yaml @@ -1,6 +1,7 @@ seclab-taskflow-agent: - type: personality version: 1 + filetype: personality + filekey: personalities/examples/banana_expert.yaml personality: | You are a bananas expert. diff --git a/personalities/examples/echo.yaml b/personalities/examples/echo.yaml index 2c080e8..87837f6 100644 --- a/personalities/examples/echo.yaml +++ b/personalities/examples/echo.yaml @@ -1,6 +1,7 @@ seclab-taskflow-agent: - type: personality version: 1 + filetype: personality + filekey: personalities/examples/echo.yaml personality: | You are a simple echo bot. You use echo tools to echo things. @@ -9,5 +10,5 @@ task: | Echo user inputs using the echo tools. toolboxes: - - echo + - toolboxes/echo.yaml diff --git a/personalities/examples/example_triage_agent.yaml b/personalities/examples/example_triage_agent.yaml index fd09711..43943d8 100644 --- a/personalities/examples/example_triage_agent.yaml +++ b/personalities/examples/example_triage_agent.yaml @@ -1,6 +1,7 @@ seclab-taskflow-agent: - type: personality version: 1 + filetype: personality + filekey: personalities/examples/example_triage_agent.yaml personality: | You are a triage agent. You route tasks to other agents. diff --git a/personalities/examples/fruit_expert.yaml b/personalities/examples/fruit_expert.yaml index 12f0f31..dfb608c 100644 --- a/personalities/examples/fruit_expert.yaml +++ b/personalities/examples/fruit_expert.yaml @@ -1,6 +1,7 @@ seclab-taskflow-agent: - type: personality version: 1 + filetype: personality + filekey: personalities/examples/fruit_expert.yaml personality: | Your name is Bob. You are a fruit expert. diff --git a/personalities/examples/orange_expert.yaml b/personalities/examples/orange_expert.yaml index 63153b3..76446c0 100644 --- a/personalities/examples/orange_expert.yaml +++ b/personalities/examples/orange_expert.yaml @@ -1,6 +1,7 @@ seclab-taskflow-agent: - type: personality version: 1 + filetype: personality + filekey: personalities/examples/orange_expert.yaml personality: | You are an oranges expert. diff --git a/prompts/examples/example_prompt.yaml b/prompts/examples/example_prompt.yaml index ebeca8c..fea1179 100644 --- a/prompts/examples/example_prompt.yaml +++ b/prompts/examples/example_prompt.yaml @@ -1,6 +1,7 @@ seclab-taskflow-agent: - type: prompt version: 1 + filetype: prompt + filekey: prompts/examples/example_prompt.yaml prompt: | Tell me more about bananas as well. diff --git a/taskflows/CVE-2023-2283/CVE-2023-2283.yaml b/taskflows/CVE-2023-2283/CVE-2023-2283.yaml index f3a018a..8fa85a9 100644 --- a/taskflows/CVE-2023-2283/CVE-2023-2283.yaml +++ b/taskflows/CVE-2023-2283/CVE-2023-2283.yaml @@ -1,22 +1,23 @@ seclab-taskflow-agent: - type: taskflow version: 1 + filetype: taskflow + filekey: taskflows/CVE-2023-2283/CVE-2023-2283.yaml taskflow: - task: must_complete: true headless: true agents: - - assistant + - personalities/assistant.yaml user_prompt: | Clear the memory cache. toolboxes: - - memcache + - toolboxes/memcache.yaml - task: model: gpt-4.1 must_complete: false agents: - - c_auditer + - personalities/c_auditer.yaml user_prompt: | You are auditing code using the `libssh-mirror/libssh-codeql` CodeQL database. @@ -76,15 +77,15 @@ taskflow: 6. Make small and concise single line notes while you work. Update the existing value for `notes` in memory as you work. toolboxes: - - codeql - - memcache + - toolboxes/codeql.yaml + - toolboxes/memcache.yaml - task: must_complete: true agents: - - c_auditer + - personalities/c_auditer.yaml user_prompt: | Fetch your audit notes from memory using the `notes` key. Do not perform any additional security review, only show me your notes. toolboxes: - - memcache + - toolboxes/memcache.yaml diff --git a/taskflows/examples/echo.yaml b/taskflows/examples/echo.yaml index 1174f7a..434dab7 100644 --- a/taskflows/examples/echo.yaml +++ b/taskflows/examples/echo.yaml @@ -1,6 +1,7 @@ seclab-taskflow-agent: - type: taskflow version: 1 + filetype: taskflow + filekey: taskflows/examples/echo.yaml taskflow: - task: @@ -8,13 +9,13 @@ taskflow: max_steps: 5 must_complete: true agents: - - echo + - personalities/examples/echo.yaml user_prompt: | Hello - task: must_complete: true agents: - - echo + - personalities/examples/echo.yaml user_prompt: | Goodbye env: diff --git a/taskflows/examples/example.yaml b/taskflows/examples/example.yaml index 24fc07a..e87fb4a 100644 --- a/taskflows/examples/example.yaml +++ b/taskflows/examples/example.yaml @@ -1,6 +1,7 @@ seclab-taskflow-agent: - type: taskflow version: 1 + filetype: taskflow + filekey: taskflows/examples/example.yaml taskflow: - task: @@ -12,8 +13,8 @@ taskflow: must_complete: true # taskflows can set a primary (first entry) and handoff (additional entries) agent agents: - - c_auditer - - fruit_expert + - personalities/c_auditer.yaml + - personalities/examples/fruit_expert.yaml user_prompt: | Store an example vulnerable C program that uses `strcpy` in the `vulnerable_c_example` memory key and explain why `strcpy` @@ -34,13 +35,13 @@ taskflow: # this normally only has the memcache toolbox, but we extend it here with # the GHSA toolbox toolboxes: - - memcache - - codeql + - toolboxes/memcache.yaml + - toolboxes/codeql.yaml - task: must_complete: true model: gpt-4.1 agents: - - c_auditer + - personalities/c_auditer.yaml user_prompt: | Retrieve C code for security review from the `vulnerable_c_example` memory key and perform a review. @@ -50,7 +51,7 @@ taskflow: MEMCACHE_STATE_DIR: "example_taskflow/" MEMCACHE_BACKEND: "dictionary_file" toolboxes: - - memcache + - toolboxes/memcache.yaml # headless mode does not prompt for tool call confirms configured for a server # note: this will auto-allow, if you want control over potentially dangerous # tool calls, then you should NOT run a task in headless mode (default: false) @@ -63,6 +64,6 @@ taskflow: - task: repeat_prompt: true agents: - - assistant + - personalities/assistant.yaml user_prompt: | What kind of fruit is {{ RESULT }}? diff --git a/taskflows/examples/example_globals.yaml b/taskflows/examples/example_globals.yaml index c63d433..7f785d4 100644 --- a/taskflows/examples/example_globals.yaml +++ b/taskflows/examples/example_globals.yaml @@ -1,13 +1,14 @@ seclab-taskflow-agent: - type: taskflow version: 1 + filetype: taskflow + filekey: taskflows/examples/example_globals.yaml globals: fruit: bananas taskflow: - task: agents: - - fruit_expert + - personalities/examples/fruit_expert.yaml user_prompt: | Tell me more about {{ GLOBALS_fruit }}. diff --git a/taskflows/examples/example_inputs.yaml b/taskflows/examples/example_inputs.yaml index 8cc136c..28cb1f7 100644 --- a/taskflows/examples/example_inputs.yaml +++ b/taskflows/examples/example_inputs.yaml @@ -1,11 +1,12 @@ seclab-taskflow-agent: - type: taskflow version: 1 + filetype: taskflow + filekey: taskflows/examples/example_inputs.yaml taskflow: - task: agents: - - fruit_expert + - personalities/examples/fruit_expert.yaml inputs: fruit: apples user_prompt: | diff --git a/taskflows/examples/example_large_list_result_iter.yaml b/taskflows/examples/example_large_list_result_iter.yaml index 2733351..082f057 100644 --- a/taskflows/examples/example_large_list_result_iter.yaml +++ b/taskflows/examples/example_large_list_result_iter.yaml @@ -1,24 +1,25 @@ seclab-taskflow-agent: - type: taskflow version: 1 + filetype: taskflow + filekey: taskflows/examples/example_large_list_result_iter.yaml taskflow: - task: exclude_from_context: true must_complete: true agents: - - assistant + - personalities/assistant.yaml user_prompt: | Fetch all the open pull requests from `github/codeql` github repository. You do not need to provide a summary of the results. toolboxes: - - github_official + - toolboxes/github_official.yaml env: GITHUB_MCP_TOOLSETS: pull_requests - task: must_complete: true repeat_prompt: true agents: - - assistant + - personalities/assistant.yaml user_prompt: | Echo this: The title is {{ RESULT_title }} and the url is {{ RESULT_url }}. diff --git a/taskflows/examples/example_repeat_prompt.yaml b/taskflows/examples/example_repeat_prompt.yaml index 4347aef..0524c3d 100644 --- a/taskflows/examples/example_repeat_prompt.yaml +++ b/taskflows/examples/example_repeat_prompt.yaml @@ -1,13 +1,14 @@ seclab-taskflow-agent: - type: taskflow version: 1 + filetype: taskflow + filekey: taskflows/examples/example_repeat_prompt.yaml taskflow: - task: max_steps: 5 must_complete: true agents: - - assistant + - personalities/assistant.yaml user_prompt: | Store the json array [1, 2, 3] in memory under the `test_repeat_prompt` key as a json object, then retrieve @@ -16,13 +17,13 @@ taskflow: MEMCACHE_STATE_DIR: "example_repeat_prompt_taskflow/" MEMCACHE_BACKEND: "dictionary_file" toolboxes: - - memcache + - toolboxes/memcache.yaml - task: # if the last mcp tool result is iterable # repeat_prompt can iter those results must_complete: true repeat_prompt: true agents: - - assistant + - personalities/assistant.yaml user_prompt: | What is the integer value of {{ RESULT }}? diff --git a/taskflows/examples/example_repeat_prompt_async.yaml b/taskflows/examples/example_repeat_prompt_async.yaml index 6897dc4..bec7bf1 100644 --- a/taskflows/examples/example_repeat_prompt_async.yaml +++ b/taskflows/examples/example_repeat_prompt_async.yaml @@ -1,13 +1,14 @@ seclab-taskflow-agent: - type: taskflow version: 1 + filetype: taskflow + filekey: taskflows/examples/example_repeat_prompt_async.yaml taskflow: - task: max_steps: 5 must_complete: true agents: - - assistant + - personalities/assistant.yaml user_prompt: | Store the json array [1, 2, 3] in memory under the `test_repeat_prompt` key as a json object, then retrieve @@ -16,7 +17,7 @@ taskflow: MEMCACHE_STATE_DIR: "example_repeat_prompt_taskflow/" MEMCACHE_BACKEND: "dictionary_file" toolboxes: - - memcache + - toolboxes/memcache.yaml - task: # if the last mcp tool result is iterable # repeat_prompt can iter those results @@ -27,6 +28,6 @@ taskflow: # you can also limit the max concurrent tasks (default 5) async_limit: 2 agents: - - assistant + - personalities/assistant.yaml user_prompt: | What is the integer value of {{ RESULT }}? diff --git a/taskflows/examples/example_repeat_prompt_dictionary.yaml b/taskflows/examples/example_repeat_prompt_dictionary.yaml index 37545b4..9c43e11 100644 --- a/taskflows/examples/example_repeat_prompt_dictionary.yaml +++ b/taskflows/examples/example_repeat_prompt_dictionary.yaml @@ -1,13 +1,14 @@ seclab-taskflow-agent: - type: taskflow version: 1 + filetype: taskflow + filekey: taskflows/examples/example_repeat_prompt_dictionary.yaml taskflow: - task: max_steps: 5 must_complete: true agents: - - assistant + - personalities/assistant.yaml user_prompt: | Store the json array [{index : 1, value : 2}, {index : 2, value : 4}, {index : 3, value : 6}] in memory under the `test_repeat_prompt` key @@ -17,13 +18,13 @@ taskflow: MEMCACHE_STATE_DIR: "example_repeat_prompt_taskflow/" MEMCACHE_BACKEND: "dictionary_file" toolboxes: - - memcache + - toolboxes/memcache.yaml - task: # if the last mcp tool result is iterable # repeat_prompt can iter those results must_complete: true repeat_prompt: true agents: - - assistant + - personalities/assistant.yaml user_prompt: | What is the value of {{ RESULT_index }} + {{ RESULT_value }}? diff --git a/taskflows/examples/example_reusable_prompt.yaml b/taskflows/examples/example_reusable_prompt.yaml index 799b8bb..7b660c0 100644 --- a/taskflows/examples/example_reusable_prompt.yaml +++ b/taskflows/examples/example_reusable_prompt.yaml @@ -1,12 +1,13 @@ seclab-taskflow-agent: - type: taskflow version: 1 + filetype: taskflow + filekey: taskflows/examples/example_reusable_prompt.yaml taskflow: - task: agents: - - fruit_expert + - personalities/examples/fruit_expert.yaml user_prompt: | Tell me more about apples. - {{ PROMPTS_examples/example_prompt }} + {{ PROMPTS_prompts/examples/example_prompt.yaml }} diff --git a/taskflows/examples/example_reusable_taskflows.yaml b/taskflows/examples/example_reusable_taskflows.yaml index 6d45314..f358d46 100644 --- a/taskflows/examples/example_reusable_taskflows.yaml +++ b/taskflows/examples/example_reusable_taskflows.yaml @@ -1,10 +1,11 @@ seclab-taskflow-agent: - type: taskflow version: 1 + filetype: taskflow + filekey: taskflows/examples/example_reusable_taskflows.yaml taskflow: - task: # with the `uses` directive we can reuse single task taskflows - uses: single_step_taskflow + uses: taskflows/examples/single_step_taskflow.yaml # and optionally override any of its configurations model: gpt-4o diff --git a/taskflows/examples/example_triage_taskflow.yaml b/taskflows/examples/example_triage_taskflow.yaml index 7910b20..01ea450 100644 --- a/taskflows/examples/example_triage_taskflow.yaml +++ b/taskflows/examples/example_triage_taskflow.yaml @@ -1,40 +1,41 @@ # a simple example of the triage Agent pattern seclab-taskflow-agent: - type: taskflow version: 1 + filetype: taskflow + filekey: taskflows/examples/example_triage_taskflow.yaml taskflow: - task: must_complete: true agents: - - assistant + - personalities/assistant.yaml user_prompt: | Store the json array ["apples", "oranges", "bananas"] in the `fruits` memory key. env: MEMCACHE_STATE_DIR: "example_taskflow/" MEMCACHE_BACKEND: "dictionary_file" toolboxes: - - memcache + - toolboxes/memcache.yaml - task: must_complete: true agents: - - assistant + - personalities/assistant.yaml user_prompt: | Retrieve the contents of the `fruits` memory key. env: MEMCACHE_STATE_DIR: "example_taskflow/" MEMCACHE_BACKEND: "dictionary_file" toolboxes: - - memcache + - toolboxes/memcache.yaml - task: model: gpt-4.1 repeat_prompt: true agents: # primary agent for this task - - example_triage_agent + - personalities/examples/example_triage_agent.yaml # handoff agents - - apple_expert - - orange_expert - - banana_expert + - personalities/examples/apple_expert.yaml + - personalities/examples/orange_expert.yaml + - personalities/examples/banana_expert.yaml user_prompt: | Tell me more about how {{ RESULT }} are grown. diff --git a/taskflows/examples/single_step_taskflow.yaml b/taskflows/examples/single_step_taskflow.yaml index fef5002..e0a8bc3 100644 --- a/taskflows/examples/single_step_taskflow.yaml +++ b/taskflows/examples/single_step_taskflow.yaml @@ -1,11 +1,12 @@ seclab-taskflow-agent: - type: taskflow version: 1 + filetype: taskflow + filekey: taskflows/examples/single_step_taskflow.yaml taskflow: - task: model: gpt-4.1 agents: - - assistant + - personalities/assistant.yaml user_prompt: | Explain the plot of William Gibson's Neuromancer in a single paragraph. diff --git a/toolboxes/codeql.yaml b/toolboxes/codeql.yaml index b8002c3..60683da 100644 --- a/toolboxes/codeql.yaml +++ b/toolboxes/codeql.yaml @@ -1,6 +1,7 @@ seclab-taskflow-agent: - type: toolbox version: 1 + filetype: toolbox + filekey: toolboxes/codeql.yaml server_params: kind: streamable diff --git a/toolboxes/echo.yaml b/toolboxes/echo.yaml index b4ca510..149f8df 100644 --- a/toolboxes/echo.yaml +++ b/toolboxes/echo.yaml @@ -1,6 +1,7 @@ seclab-taskflow-agent: - type: toolbox version: 1 + filetype: toolbox + filekey: toolboxes/echo.yaml server_params: kind: stdio diff --git a/toolboxes/github_official.yaml b/toolboxes/github_official.yaml index 0bfa367..ec39333 100644 --- a/toolboxes/github_official.yaml +++ b/toolboxes/github_official.yaml @@ -1,6 +1,7 @@ seclab-taskflow-agent: - type: toolbox version: 1 + filetype: toolbox + filekey: toolboxes/github_official.yaml server_params: kind: streamable diff --git a/toolboxes/logbook.yaml b/toolboxes/logbook.yaml index ef46808..024e59b 100644 --- a/toolboxes/logbook.yaml +++ b/toolboxes/logbook.yaml @@ -1,6 +1,7 @@ seclab-taskflow-agent: - type: toolbox version: 1 + filetype: toolbox + filekey: toolboxes/logbook.yaml server_params: kind: stdio @@ -12,4 +13,4 @@ server_params: # the list of tools that you want the framework to confirm with the user before executing # use this to guard rail any potentially dangerous functions from MCP servers confirm: - - logbook_erase + - toolboxes/logbook.yaml_erase diff --git a/toolboxes/memcache.yaml b/toolboxes/memcache.yaml index d6f5036..918b49f 100644 --- a/toolboxes/memcache.yaml +++ b/toolboxes/memcache.yaml @@ -1,6 +1,7 @@ seclab-taskflow-agent: - type: toolbox version: 1 + filetype: toolbox + filekey: toolboxes/memcache.yaml server_params: kind: stdio @@ -13,4 +14,4 @@ server_params: # the list of tools that you want the framework to confirm with the user before executing # use this to guard rail any potentially dangerous functions from MCP servers confirm: - - memcache_clear_cache + - toolboxes/memcache.yaml_clear_cache diff --git a/yaml_parser.py b/yaml_parser.py index f02d21f..ea6b0a9 100644 --- a/yaml_parser.py +++ b/yaml_parser.py @@ -1,32 +1,25 @@ import os import yaml from pathlib import Path +from collections.abc import Iterator import logging class YamlParser: - def __init__(self, path: str | Path): - self.path = Path(path) + def __init__(self, rootpath: Path): + self.rootpath = rootpath.absolute() - def get_yaml_dict(self, recurse=True, dir_namespace=False) -> dict: + def get_yaml_dict(self, files: Iterator) -> dict: """Return a directory of yaml files as a dictionary of file name indexed yaml dicts""" - dir_path = Path(__file__).parent.resolve() / Path(self.path) yaml_dict = {} - if recurse: - files = dir_path.rglob('*') - else: - files = list(dir_path.iterdir()) for f in files: if f.is_file() and not f.name.startswith('.') and f.suffix in ['.yaml', '.yml']: try: - with open(os.path.join(dir_path, f)) as stream: + with open(f) as stream: try: p = yaml.safe_load(stream) - # namespace to a full relative path e.g. /subdir/file - if dir_namespace: - namespaced_stem = str(f.relative_to(dir_path).with_suffix('')) - yaml_dict[namespaced_stem] = p - else: - yaml_dict[Path(f).stem] = p + # Use the relative path as the key in the dict. + namespaced_stem = str(f.relative_to(self.rootpath)) + yaml_dict[namespaced_stem] = p except yaml.YAMLError as e: logging.error(e) except FileNotFoundError as e: From 3eb030760943bfde16fc45f50b7cbf89cde37b98 Mon Sep 17 00:00:00 2001 From: Kevin Backhouse Date: Fri, 17 Oct 2025 23:47:28 +0100 Subject: [PATCH 2/3] Update filekeys and add a test --- .github/workflows/basictest.yaml | 44 +++++++++++++++++++ main.py | 8 ++-- mcp_utils.py | 13 +++++- personalities/assistant.yaml | 2 +- personalities/c_auditer.yaml | 6 +-- personalities/examples/apple_expert.yaml | 2 +- personalities/examples/banana_expert.yaml | 2 +- personalities/examples/echo.yaml | 4 +- .../examples/example_triage_agent.yaml | 2 +- personalities/examples/fruit_expert.yaml | 2 +- personalities/examples/orange_expert.yaml | 2 +- prompts/examples/example_prompt.yaml | 2 +- taskflows/CVE-2023-2283/CVE-2023-2283.yaml | 16 +++---- taskflows/examples/echo.yaml | 6 +-- taskflows/examples/example.yaml | 16 +++---- taskflows/examples/example_globals.yaml | 5 +-- taskflows/examples/example_inputs.yaml | 4 +- .../example_large_list_result_iter.yaml | 8 ++-- taskflows/examples/example_repeat_prompt.yaml | 8 ++-- .../examples/example_repeat_prompt_async.yaml | 8 ++-- .../example_repeat_prompt_dictionary.yaml | 8 ++-- .../examples/example_reusable_prompt.yaml | 6 +-- .../examples/example_reusable_taskflows.yaml | 4 +- .../examples/example_triage_taskflow.yaml | 18 ++++---- taskflows/examples/single_step_taskflow.yaml | 4 +- toolboxes/codeql.yaml | 2 +- toolboxes/echo.yaml | 2 +- toolboxes/github_official.yaml | 2 +- toolboxes/logbook.yaml | 4 +- toolboxes/memcache.yaml | 4 +- 30 files changed, 134 insertions(+), 80 deletions(-) create mode 100644 .github/workflows/basictest.yaml diff --git a/.github/workflows/basictest.yaml b/.github/workflows/basictest.yaml new file mode 100644 index 0000000..67dbbca --- /dev/null +++ b/.github/workflows/basictest.yaml @@ -0,0 +1,44 @@ +name: Basic test - run the examples to check for errors + +on: + pull_request + +permissions: + contents: read + +jobs: + Linux: + runs-on: ubuntu-latest + steps: + - name: Setup Python + uses: actions/setup-python@v5 + + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup Python venv + run: | + python -m venv .venv + source .venv/bin/activate + python -m pip install -r requirements.txt + + - name: Run tests + env: + COPILOT_TOKEN: ${{ secrets.COPILOT_TOKEN }} + run: | + python main.py -p GitHubSecurityLab/seclab-taskflow-agent/personalities/assistant 'explain modems to me please' + python main.py -p GitHubSecurityLab/seclab-taskflow-agent/personalities/c_auditer 'explain modems to me please' + python main.py -p GitHubSecurityLab/seclab-taskflow-agent/personalities/examples/echo 'explain modems to me please' + python main.py -t GitHubSecurityLab/seclab-taskflow-agent/taskflows/CVE-2023-2283/CVE-2023-2283 + python main.py -t GitHubSecurityLab/seclab-taskflow-agent/taskflows/examples/echo + python main.py -t GitHubSecurityLab/seclab-taskflow-agent/taskflows/examples/example + python main.py -t GitHubSecurityLab/seclab-taskflow-agent/taskflows/examples/example_globals + python main.py -t GitHubSecurityLab/seclab-taskflow-agent/taskflows/examples/example_inputs + python main.py -t GitHubSecurityLab/seclab-taskflow-agent/taskflows/examples/example_large_list_result_iter + python main.py -t GitHubSecurityLab/seclab-taskflow-agent/taskflows/examples/example_repeat_prompt + python main.py -t GitHubSecurityLab/seclab-taskflow-agent/taskflows/examples/example_repeat_prompt_async + python main.py -t GitHubSecurityLab/seclab-taskflow-agent/taskflows/examples/example_repeat_prompt_dictionary + python main.py -t GitHubSecurityLab/seclab-taskflow-agent/taskflows/examples/example_reusable_prompt + python main.py -t GitHubSecurityLab/seclab-taskflow-agent/taskflows/examples/example_reusable_taskflows + python main.py -t GitHubSecurityLab/seclab-taskflow-agent/taskflows/examples/example_triage_taskflow + python main.py -t GitHubSecurityLab/seclab-taskflow-agent/taskflows/examples/single_step_taskflow diff --git a/main.py b/main.py index 0d60e16..fbb329f 100644 --- a/main.py +++ b/main.py @@ -24,7 +24,7 @@ from typing import Any from shell_utils import shell_tool_call -from mcp_utils import DEFAULT_MCP_CLIENT_SESSION_TIMEOUT, ReconnectingMCPServerStdio, AsyncDebugMCPServerStdio, MCPNamespaceWrap, mcp_client_params, mcp_system_prompt, StreamableMCPThread +from mcp_utils import DEFAULT_MCP_CLIENT_SESSION_TIMEOUT, ReconnectingMCPServerStdio, AsyncDebugMCPServerStdio, MCPNamespaceWrap, mcp_client_params, mcp_system_prompt, StreamableMCPThread, compress_name from render_utils import render_model_output, flush_async_output from env_utils import TmpEnv from yaml_parser import YamlParser @@ -256,7 +256,7 @@ async def mcp_session_task( for handoff_agent in list(agents.keys())[1:]: handoffs.append(TaskAgent( # XXX: name has to be descriptive for an effective handoff - name=handoff_agent, + name=compress_name(handoff_agent), instructions=prompt_with_handoff_instructions( mcp_system_prompt( agents[handoff_agent]['personality'], @@ -400,7 +400,7 @@ async def on_handoff_hook( if p: personality = available_tools.personalities.get(p) if personality is None: - raise ValueError("No such personality!") + raise ValueError(f"No such personality: {p}") await deploy_task_agents( available_tools, @@ -414,7 +414,7 @@ async def on_handoff_hook( taskflow = available_tools.taskflows.get(t) if taskflow is None: - raise ValueError("No such taskflow!") + raise ValueError(f"No such taskflow: {t}") await render_model_output(f"** 🤖💪 Running Task Flow: {t}\n") diff --git a/mcp_utils.py b/mcp_utils.py index 5fd2187..c1fb40e 100644 --- a/mcp_utils.py +++ b/mcp_utils.py @@ -9,6 +9,7 @@ import os import socket import signal +import hashlib from urllib.parse import urlparse from mcp.types import CallToolResult, TextContent @@ -18,6 +19,16 @@ DEFAULT_MCP_CLIENT_SESSION_TIMEOUT = 120 +# The openai API complains if the name of a tool is longer than 64 +# chars. But we're encouraging people to use long descriptive +# filekeys to avoid accidental collisions, so it's very easy to go +# over the limit. So this function converts a name to a 12 character +# hash. +def compress_name(name): + m = hashlib.sha256() + m.update(name.encode('utf-8')) + return m.hexdigest()[:12] + # A process management class for running in-process MCP streamable servers class StreamableMCPThread(Thread): """Process management for local streamable MCP servers""" @@ -221,7 +232,7 @@ class MCPNamespaceWrap: def __init__(self, confirms, obj): self.confirms = confirms self._obj = obj - self.namespace = f"{obj.name.upper().replace(' ', '_').replace('/','-')}_" + self.namespace = compress_name(obj.name) def __getattr__(self, name): attr = getattr(self._obj, name) diff --git a/personalities/assistant.yaml b/personalities/assistant.yaml index c46b9c9..6d3bb35 100644 --- a/personalities/assistant.yaml +++ b/personalities/assistant.yaml @@ -1,7 +1,7 @@ seclab-taskflow-agent: version: 1 filetype: personality - filekey: personalities/assistant.yaml + filekey: GitHubSecurityLab/seclab-taskflow-agent/personalities/assistant personality: | You are a helpful assistant. diff --git a/personalities/c_auditer.yaml b/personalities/c_auditer.yaml index bb2a4b1..556b73b 100644 --- a/personalities/c_auditer.yaml +++ b/personalities/c_auditer.yaml @@ -1,7 +1,7 @@ seclab-taskflow-agent: version: 1 filetype: personality - filekey: personalities/c_auditer.yaml + filekey: GitHubSecurityLab/seclab-taskflow-agent/personalities/c_auditer personality: | Your name is Ronald. You are a C programming language security expert. @@ -15,5 +15,5 @@ task: | your findings where possible. toolboxes: - - toolboxes/memcache.yaml - - toolboxes/codeql.yaml + - GitHubSecurityLab/seclab-taskflow-agent/toolboxes/memcache + - GitHubSecurityLab/seclab-taskflow-agent/toolboxes/codeql diff --git a/personalities/examples/apple_expert.yaml b/personalities/examples/apple_expert.yaml index fd271e0..16683fe 100644 --- a/personalities/examples/apple_expert.yaml +++ b/personalities/examples/apple_expert.yaml @@ -1,7 +1,7 @@ seclab-taskflow-agent: version: 1 filetype: personality - filekey: personalities/examples/apple_expert.yaml + filekey: GitHubSecurityLab/seclab-taskflow-agent/personalities/examples/apple_expert personality: | You are an apples expert. diff --git a/personalities/examples/banana_expert.yaml b/personalities/examples/banana_expert.yaml index 5693426..edb09de 100644 --- a/personalities/examples/banana_expert.yaml +++ b/personalities/examples/banana_expert.yaml @@ -1,7 +1,7 @@ seclab-taskflow-agent: version: 1 filetype: personality - filekey: personalities/examples/banana_expert.yaml + filekey: GitHubSecurityLab/seclab-taskflow-agent/personalities/examples/banana_expert personality: | You are a bananas expert. diff --git a/personalities/examples/echo.yaml b/personalities/examples/echo.yaml index 87837f6..25152c9 100644 --- a/personalities/examples/echo.yaml +++ b/personalities/examples/echo.yaml @@ -1,7 +1,7 @@ seclab-taskflow-agent: version: 1 filetype: personality - filekey: personalities/examples/echo.yaml + filekey: GitHubSecurityLab/seclab-taskflow-agent/personalities/examples/echo personality: | You are a simple echo bot. You use echo tools to echo things. @@ -10,5 +10,5 @@ task: | Echo user inputs using the echo tools. toolboxes: - - toolboxes/echo.yaml + - GitHubSecurityLab/seclab-taskflow-agent/toolboxes/echo diff --git a/personalities/examples/example_triage_agent.yaml b/personalities/examples/example_triage_agent.yaml index 43943d8..246a414 100644 --- a/personalities/examples/example_triage_agent.yaml +++ b/personalities/examples/example_triage_agent.yaml @@ -1,7 +1,7 @@ seclab-taskflow-agent: version: 1 filetype: personality - filekey: personalities/examples/example_triage_agent.yaml + filekey: GitHubSecurityLab/seclab-taskflow-agent/personalities/examples/example_triage_agent personality: | You are a triage agent. You route tasks to other agents. diff --git a/personalities/examples/fruit_expert.yaml b/personalities/examples/fruit_expert.yaml index dfb608c..e987904 100644 --- a/personalities/examples/fruit_expert.yaml +++ b/personalities/examples/fruit_expert.yaml @@ -1,7 +1,7 @@ seclab-taskflow-agent: version: 1 filetype: personality - filekey: personalities/examples/fruit_expert.yaml + filekey: GitHubSecurityLab/seclab-taskflow-agent/personalities/examples/fruit_expert personality: | Your name is Bob. You are a fruit expert. diff --git a/personalities/examples/orange_expert.yaml b/personalities/examples/orange_expert.yaml index 76446c0..aa4b953 100644 --- a/personalities/examples/orange_expert.yaml +++ b/personalities/examples/orange_expert.yaml @@ -1,7 +1,7 @@ seclab-taskflow-agent: version: 1 filetype: personality - filekey: personalities/examples/orange_expert.yaml + filekey: GitHubSecurityLab/seclab-taskflow-agent/personalities/examples/orange_expert personality: | You are an oranges expert. diff --git a/prompts/examples/example_prompt.yaml b/prompts/examples/example_prompt.yaml index fea1179..1e9f38b 100644 --- a/prompts/examples/example_prompt.yaml +++ b/prompts/examples/example_prompt.yaml @@ -1,7 +1,7 @@ seclab-taskflow-agent: version: 1 filetype: prompt - filekey: prompts/examples/example_prompt.yaml + filekey: GitHubSecurityLab/seclab-taskflow-agent/prompts/examples/example_prompt prompt: | Tell me more about bananas as well. diff --git a/taskflows/CVE-2023-2283/CVE-2023-2283.yaml b/taskflows/CVE-2023-2283/CVE-2023-2283.yaml index 8fa85a9..9f30f29 100644 --- a/taskflows/CVE-2023-2283/CVE-2023-2283.yaml +++ b/taskflows/CVE-2023-2283/CVE-2023-2283.yaml @@ -1,23 +1,23 @@ seclab-taskflow-agent: version: 1 filetype: taskflow - filekey: taskflows/CVE-2023-2283/CVE-2023-2283.yaml + filekey: GitHubSecurityLab/seclab-taskflow-agent/taskflows/CVE-2023-2283/CVE-2023-2283 taskflow: - task: must_complete: true headless: true agents: - - personalities/assistant.yaml + - GitHubSecurityLab/seclab-taskflow-agent/personalities/assistant user_prompt: | Clear the memory cache. toolboxes: - - toolboxes/memcache.yaml + - GitHubSecurityLab/seclab-taskflow-agent/toolboxes/memcache - task: model: gpt-4.1 must_complete: false agents: - - personalities/c_auditer.yaml + - GitHubSecurityLab/seclab-taskflow-agent/personalities/c_auditer user_prompt: | You are auditing code using the `libssh-mirror/libssh-codeql` CodeQL database. @@ -77,15 +77,15 @@ taskflow: 6. Make small and concise single line notes while you work. Update the existing value for `notes` in memory as you work. toolboxes: - - toolboxes/codeql.yaml - - toolboxes/memcache.yaml + - GitHubSecurityLab/seclab-taskflow-agent/toolboxes/codeql + - GitHubSecurityLab/seclab-taskflow-agent/toolboxes/memcache - task: must_complete: true agents: - - personalities/c_auditer.yaml + - GitHubSecurityLab/seclab-taskflow-agent/personalities/c_auditer user_prompt: | Fetch your audit notes from memory using the `notes` key. Do not perform any additional security review, only show me your notes. toolboxes: - - toolboxes/memcache.yaml + - GitHubSecurityLab/seclab-taskflow-agent/toolboxes/memcache diff --git a/taskflows/examples/echo.yaml b/taskflows/examples/echo.yaml index 434dab7..c01334a 100644 --- a/taskflows/examples/echo.yaml +++ b/taskflows/examples/echo.yaml @@ -1,7 +1,7 @@ seclab-taskflow-agent: version: 1 filetype: taskflow - filekey: taskflows/examples/echo.yaml + filekey: GitHubSecurityLab/seclab-taskflow-agent/taskflows/examples/echo taskflow: - task: @@ -9,13 +9,13 @@ taskflow: max_steps: 5 must_complete: true agents: - - personalities/examples/echo.yaml + - GitHubSecurityLab/seclab-taskflow-agent/personalities/examples/echo user_prompt: | Hello - task: must_complete: true agents: - - personalities/examples/echo.yaml + - GitHubSecurityLab/seclab-taskflow-agent/personalities/examples/echo user_prompt: | Goodbye env: diff --git a/taskflows/examples/example.yaml b/taskflows/examples/example.yaml index e87fb4a..15203dd 100644 --- a/taskflows/examples/example.yaml +++ b/taskflows/examples/example.yaml @@ -1,7 +1,7 @@ seclab-taskflow-agent: version: 1 filetype: taskflow - filekey: taskflows/examples/example.yaml + filekey: GitHubSecurityLab/seclab-taskflow-agent/taskflows/examples/example taskflow: - task: @@ -13,8 +13,8 @@ taskflow: must_complete: true # taskflows can set a primary (first entry) and handoff (additional entries) agent agents: - - personalities/c_auditer.yaml - - personalities/examples/fruit_expert.yaml + - GitHubSecurityLab/seclab-taskflow-agent/personalities/c_auditer + - GitHubSecurityLab/seclab-taskflow-agent/personalities/examples/fruit_expert user_prompt: | Store an example vulnerable C program that uses `strcpy` in the `vulnerable_c_example` memory key and explain why `strcpy` @@ -35,13 +35,13 @@ taskflow: # this normally only has the memcache toolbox, but we extend it here with # the GHSA toolbox toolboxes: - - toolboxes/memcache.yaml - - toolboxes/codeql.yaml + - GitHubSecurityLab/seclab-taskflow-agent/toolboxes/memcache + - GitHubSecurityLab/seclab-taskflow-agent/toolboxes/codeql - task: must_complete: true model: gpt-4.1 agents: - - personalities/c_auditer.yaml + - GitHubSecurityLab/seclab-taskflow-agent/personalities/c_auditer user_prompt: | Retrieve C code for security review from the `vulnerable_c_example` memory key and perform a review. @@ -51,7 +51,7 @@ taskflow: MEMCACHE_STATE_DIR: "example_taskflow/" MEMCACHE_BACKEND: "dictionary_file" toolboxes: - - toolboxes/memcache.yaml + - GitHubSecurityLab/seclab-taskflow-agent/toolboxes/memcache # headless mode does not prompt for tool call confirms configured for a server # note: this will auto-allow, if you want control over potentially dangerous # tool calls, then you should NOT run a task in headless mode (default: false) @@ -64,6 +64,6 @@ taskflow: - task: repeat_prompt: true agents: - - personalities/assistant.yaml + - GitHubSecurityLab/seclab-taskflow-agent/personalities/assistant user_prompt: | What kind of fruit is {{ RESULT }}? diff --git a/taskflows/examples/example_globals.yaml b/taskflows/examples/example_globals.yaml index 7f785d4..24c9864 100644 --- a/taskflows/examples/example_globals.yaml +++ b/taskflows/examples/example_globals.yaml @@ -1,14 +1,13 @@ seclab-taskflow-agent: version: 1 filetype: taskflow - filekey: taskflows/examples/example_globals.yaml + filekey: GitHubSecurityLab/seclab-taskflow-agent/taskflows/examples/example_globals globals: fruit: bananas taskflow: - task: agents: - - personalities/examples/fruit_expert.yaml + - GitHubSecurityLab/seclab-taskflow-agent/personalities/examples/fruit_expert user_prompt: | Tell me more about {{ GLOBALS_fruit }}. - diff --git a/taskflows/examples/example_inputs.yaml b/taskflows/examples/example_inputs.yaml index 28cb1f7..5c6d255 100644 --- a/taskflows/examples/example_inputs.yaml +++ b/taskflows/examples/example_inputs.yaml @@ -1,12 +1,12 @@ seclab-taskflow-agent: version: 1 filetype: taskflow - filekey: taskflows/examples/example_inputs.yaml + filekey: GitHubSecurityLab/seclab-taskflow-agent/taskflows/examples/example_inputs taskflow: - task: agents: - - personalities/examples/fruit_expert.yaml + - GitHubSecurityLab/seclab-taskflow-agent/personalities/examples/fruit_expert inputs: fruit: apples user_prompt: | diff --git a/taskflows/examples/example_large_list_result_iter.yaml b/taskflows/examples/example_large_list_result_iter.yaml index 082f057..8a58253 100644 --- a/taskflows/examples/example_large_list_result_iter.yaml +++ b/taskflows/examples/example_large_list_result_iter.yaml @@ -1,25 +1,25 @@ seclab-taskflow-agent: version: 1 filetype: taskflow - filekey: taskflows/examples/example_large_list_result_iter.yaml + filekey: GitHubSecurityLab/seclab-taskflow-agent/taskflows/examples/example_large_list_result_iter taskflow: - task: exclude_from_context: true must_complete: true agents: - - personalities/assistant.yaml + - GitHubSecurityLab/seclab-taskflow-agent/personalities/assistant user_prompt: | Fetch all the open pull requests from `github/codeql` github repository. You do not need to provide a summary of the results. toolboxes: - - toolboxes/github_official.yaml + - GitHubSecurityLab/seclab-taskflow-agent/toolboxes/github_official env: GITHUB_MCP_TOOLSETS: pull_requests - task: must_complete: true repeat_prompt: true agents: - - personalities/assistant.yaml + - GitHubSecurityLab/seclab-taskflow-agent/personalities/assistant user_prompt: | Echo this: The title is {{ RESULT_title }} and the url is {{ RESULT_url }}. diff --git a/taskflows/examples/example_repeat_prompt.yaml b/taskflows/examples/example_repeat_prompt.yaml index 0524c3d..470dc48 100644 --- a/taskflows/examples/example_repeat_prompt.yaml +++ b/taskflows/examples/example_repeat_prompt.yaml @@ -1,14 +1,14 @@ seclab-taskflow-agent: version: 1 filetype: taskflow - filekey: taskflows/examples/example_repeat_prompt.yaml + filekey: GitHubSecurityLab/seclab-taskflow-agent/taskflows/examples/example_repeat_prompt taskflow: - task: max_steps: 5 must_complete: true agents: - - personalities/assistant.yaml + - GitHubSecurityLab/seclab-taskflow-agent/personalities/assistant user_prompt: | Store the json array [1, 2, 3] in memory under the `test_repeat_prompt` key as a json object, then retrieve @@ -17,13 +17,13 @@ taskflow: MEMCACHE_STATE_DIR: "example_repeat_prompt_taskflow/" MEMCACHE_BACKEND: "dictionary_file" toolboxes: - - toolboxes/memcache.yaml + - GitHubSecurityLab/seclab-taskflow-agent/toolboxes/memcache - task: # if the last mcp tool result is iterable # repeat_prompt can iter those results must_complete: true repeat_prompt: true agents: - - personalities/assistant.yaml + - GitHubSecurityLab/seclab-taskflow-agent/personalities/assistant user_prompt: | What is the integer value of {{ RESULT }}? diff --git a/taskflows/examples/example_repeat_prompt_async.yaml b/taskflows/examples/example_repeat_prompt_async.yaml index bec7bf1..c5f40fd 100644 --- a/taskflows/examples/example_repeat_prompt_async.yaml +++ b/taskflows/examples/example_repeat_prompt_async.yaml @@ -1,14 +1,14 @@ seclab-taskflow-agent: version: 1 filetype: taskflow - filekey: taskflows/examples/example_repeat_prompt_async.yaml + filekey: GitHubSecurityLab/seclab-taskflow-agent/taskflows/examples/example_repeat_prompt_async taskflow: - task: max_steps: 5 must_complete: true agents: - - personalities/assistant.yaml + - GitHubSecurityLab/seclab-taskflow-agent/personalities/assistant user_prompt: | Store the json array [1, 2, 3] in memory under the `test_repeat_prompt` key as a json object, then retrieve @@ -17,7 +17,7 @@ taskflow: MEMCACHE_STATE_DIR: "example_repeat_prompt_taskflow/" MEMCACHE_BACKEND: "dictionary_file" toolboxes: - - toolboxes/memcache.yaml + - GitHubSecurityLab/seclab-taskflow-agent/toolboxes/memcache - task: # if the last mcp tool result is iterable # repeat_prompt can iter those results @@ -28,6 +28,6 @@ taskflow: # you can also limit the max concurrent tasks (default 5) async_limit: 2 agents: - - personalities/assistant.yaml + - GitHubSecurityLab/seclab-taskflow-agent/personalities/assistant user_prompt: | What is the integer value of {{ RESULT }}? diff --git a/taskflows/examples/example_repeat_prompt_dictionary.yaml b/taskflows/examples/example_repeat_prompt_dictionary.yaml index 9c43e11..f26d2e8 100644 --- a/taskflows/examples/example_repeat_prompt_dictionary.yaml +++ b/taskflows/examples/example_repeat_prompt_dictionary.yaml @@ -1,14 +1,14 @@ seclab-taskflow-agent: version: 1 filetype: taskflow - filekey: taskflows/examples/example_repeat_prompt_dictionary.yaml + filekey: GitHubSecurityLab/seclab-taskflow-agent/taskflows/examples/example_repeat_prompt_dictionary taskflow: - task: max_steps: 5 must_complete: true agents: - - personalities/assistant.yaml + - GitHubSecurityLab/seclab-taskflow-agent/personalities/assistant user_prompt: | Store the json array [{index : 1, value : 2}, {index : 2, value : 4}, {index : 3, value : 6}] in memory under the `test_repeat_prompt` key @@ -18,13 +18,13 @@ taskflow: MEMCACHE_STATE_DIR: "example_repeat_prompt_taskflow/" MEMCACHE_BACKEND: "dictionary_file" toolboxes: - - toolboxes/memcache.yaml + - GitHubSecurityLab/seclab-taskflow-agent/toolboxes/memcache - task: # if the last mcp tool result is iterable # repeat_prompt can iter those results must_complete: true repeat_prompt: true agents: - - personalities/assistant.yaml + - GitHubSecurityLab/seclab-taskflow-agent/personalities/assistant user_prompt: | What is the value of {{ RESULT_index }} + {{ RESULT_value }}? diff --git a/taskflows/examples/example_reusable_prompt.yaml b/taskflows/examples/example_reusable_prompt.yaml index 7b660c0..a1c220a 100644 --- a/taskflows/examples/example_reusable_prompt.yaml +++ b/taskflows/examples/example_reusable_prompt.yaml @@ -1,13 +1,13 @@ seclab-taskflow-agent: version: 1 filetype: taskflow - filekey: taskflows/examples/example_reusable_prompt.yaml + filekey: GitHubSecurityLab/seclab-taskflow-agent/taskflows/examples/example_reusable_prompt taskflow: - task: agents: - - personalities/examples/fruit_expert.yaml + - GitHubSecurityLab/seclab-taskflow-agent/personalities/examples/fruit_expert user_prompt: | Tell me more about apples. - {{ PROMPTS_prompts/examples/example_prompt.yaml }} + {{ GitHubSecurityLab/seclab-taskflow-agent/prompts/examples/example_prompt.yaml }} diff --git a/taskflows/examples/example_reusable_taskflows.yaml b/taskflows/examples/example_reusable_taskflows.yaml index f358d46..33cc43c 100644 --- a/taskflows/examples/example_reusable_taskflows.yaml +++ b/taskflows/examples/example_reusable_taskflows.yaml @@ -1,11 +1,11 @@ seclab-taskflow-agent: version: 1 filetype: taskflow - filekey: taskflows/examples/example_reusable_taskflows.yaml + filekey: GitHubSecurityLab/seclab-taskflow-agent/taskflows/examples/example_reusable_taskflows taskflow: - task: # with the `uses` directive we can reuse single task taskflows - uses: taskflows/examples/single_step_taskflow.yaml + uses: GitHubSecurityLab/seclab-taskflow-agent/taskflows/examples/single_step_taskflow # and optionally override any of its configurations model: gpt-4o diff --git a/taskflows/examples/example_triage_taskflow.yaml b/taskflows/examples/example_triage_taskflow.yaml index 01ea450..4ae689b 100644 --- a/taskflows/examples/example_triage_taskflow.yaml +++ b/taskflows/examples/example_triage_taskflow.yaml @@ -2,40 +2,40 @@ seclab-taskflow-agent: version: 1 filetype: taskflow - filekey: taskflows/examples/example_triage_taskflow.yaml + filekey: GitHubSecurityLab/seclab-taskflow-agent/taskflows/examples/example_triage_taskflow taskflow: - task: must_complete: true agents: - - personalities/assistant.yaml + - GitHubSecurityLab/seclab-taskflow-agent/personalities/assistant user_prompt: | Store the json array ["apples", "oranges", "bananas"] in the `fruits` memory key. env: MEMCACHE_STATE_DIR: "example_taskflow/" MEMCACHE_BACKEND: "dictionary_file" toolboxes: - - toolboxes/memcache.yaml + - GitHubSecurityLab/seclab-taskflow-agent/toolboxes/memcache - task: must_complete: true agents: - - personalities/assistant.yaml + - GitHubSecurityLab/seclab-taskflow-agent/personalities/assistant user_prompt: | Retrieve the contents of the `fruits` memory key. env: MEMCACHE_STATE_DIR: "example_taskflow/" MEMCACHE_BACKEND: "dictionary_file" toolboxes: - - toolboxes/memcache.yaml + - GitHubSecurityLab/seclab-taskflow-agent/toolboxes/memcache - task: model: gpt-4.1 repeat_prompt: true agents: # primary agent for this task - - personalities/examples/example_triage_agent.yaml + - GitHubSecurityLab/seclab-taskflow-agent/personalities/examples/example_triage_agent # handoff agents - - personalities/examples/apple_expert.yaml - - personalities/examples/orange_expert.yaml - - personalities/examples/banana_expert.yaml + - GitHubSecurityLab/seclab-taskflow-agent/personalities/examples/apple_expert + - GitHubSecurityLab/seclab-taskflow-agent/personalities/examples/orange_expert + - GitHubSecurityLab/seclab-taskflow-agent/personalities/examples/banana_expert user_prompt: | Tell me more about how {{ RESULT }} are grown. diff --git a/taskflows/examples/single_step_taskflow.yaml b/taskflows/examples/single_step_taskflow.yaml index e0a8bc3..3914ac8 100644 --- a/taskflows/examples/single_step_taskflow.yaml +++ b/taskflows/examples/single_step_taskflow.yaml @@ -1,12 +1,12 @@ seclab-taskflow-agent: version: 1 filetype: taskflow - filekey: taskflows/examples/single_step_taskflow.yaml + filekey: GitHubSecurityLab/seclab-taskflow-agent/taskflows/examples/single_step_taskflow taskflow: - task: model: gpt-4.1 agents: - - personalities/assistant.yaml + - GitHubSecurityLab/seclab-taskflow-agent/personalities/assistant user_prompt: | Explain the plot of William Gibson's Neuromancer in a single paragraph. diff --git a/toolboxes/codeql.yaml b/toolboxes/codeql.yaml index 60683da..865e9fa 100644 --- a/toolboxes/codeql.yaml +++ b/toolboxes/codeql.yaml @@ -1,7 +1,7 @@ seclab-taskflow-agent: version: 1 filetype: toolbox - filekey: toolboxes/codeql.yaml + filekey: GitHubSecurityLab/seclab-taskflow-agent/toolboxes/codeql server_params: kind: streamable diff --git a/toolboxes/echo.yaml b/toolboxes/echo.yaml index 149f8df..2dc3c99 100644 --- a/toolboxes/echo.yaml +++ b/toolboxes/echo.yaml @@ -1,7 +1,7 @@ seclab-taskflow-agent: version: 1 filetype: toolbox - filekey: toolboxes/echo.yaml + filekey: GitHubSecurityLab/seclab-taskflow-agent/toolboxes/echo server_params: kind: stdio diff --git a/toolboxes/github_official.yaml b/toolboxes/github_official.yaml index ec39333..e5f718c 100644 --- a/toolboxes/github_official.yaml +++ b/toolboxes/github_official.yaml @@ -1,7 +1,7 @@ seclab-taskflow-agent: version: 1 filetype: toolbox - filekey: toolboxes/github_official.yaml + filekey: GitHubSecurityLab/seclab-taskflow-agent/toolboxes/github_official server_params: kind: streamable diff --git a/toolboxes/logbook.yaml b/toolboxes/logbook.yaml index 024e59b..c7142a4 100644 --- a/toolboxes/logbook.yaml +++ b/toolboxes/logbook.yaml @@ -1,7 +1,7 @@ seclab-taskflow-agent: version: 1 filetype: toolbox - filekey: toolboxes/logbook.yaml + filekey: GitHubSecurityLab/seclab-taskflow-agent/toolboxes/logbook server_params: kind: stdio @@ -13,4 +13,4 @@ server_params: # the list of tools that you want the framework to confirm with the user before executing # use this to guard rail any potentially dangerous functions from MCP servers confirm: - - toolboxes/logbook.yaml_erase + - logbook_erase diff --git a/toolboxes/memcache.yaml b/toolboxes/memcache.yaml index 918b49f..9a643e7 100644 --- a/toolboxes/memcache.yaml +++ b/toolboxes/memcache.yaml @@ -1,7 +1,7 @@ seclab-taskflow-agent: version: 1 filetype: toolbox - filekey: toolboxes/memcache.yaml + filekey: GitHubSecurityLab/seclab-taskflow-agent/toolboxes/memcache server_params: kind: stdio @@ -14,4 +14,4 @@ server_params: # the list of tools that you want the framework to confirm with the user before executing # use this to guard rail any potentially dangerous functions from MCP servers confirm: - - toolboxes/memcache.yaml_clear_cache + - memcache_clear_cache From e38c9705886a4d1e6d2ac3faf706b10577209cbc Mon Sep 17 00:00:00 2001 From: Kevin Backhouse Date: Fri, 17 Oct 2025 23:50:42 +0100 Subject: [PATCH 3/3] Add python version number --- .github/workflows/basictest.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/basictest.yaml b/.github/workflows/basictest.yaml index 67dbbca..d696783 100644 --- a/.github/workflows/basictest.yaml +++ b/.github/workflows/basictest.yaml @@ -12,6 +12,8 @@ jobs: steps: - name: Setup Python uses: actions/setup-python@v5 + with: + python-version: '3.11' - name: Checkout uses: actions/checkout@v3