You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+32-24Lines changed: 32 additions & 24 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,13 +1,11 @@
1
1
Bogus change to test the updated smoketest.yml
2
2
3
-
# Seclab Taskflow Agent
3
+
# GitHub Security Lab Taskflow Agent
4
4
5
5
The Security Lab Taskflow Agent is an MCP enabled multi-Agent framework.
6
6
7
7
The Taskflow Agent is built on top of the [OpenAI Agents SDK](https://openai.github.io/openai-agents-python/).
8
8
9
-
While the Taskflow Agent does not integrate into the GitHub Dotcom Copilot UX, it does operate using the Copilot API (CAPI) as its backend, similar to Copilot IDE extensions.
10
-
11
9
## Core Concepts
12
10
13
11
The Taskflow Agent leverages a GitHub Workflow-esque YAML based grammar to perform a series of tasks using a set of Agents.
@@ -18,38 +16,48 @@ Agents are defined through [personalities](examples/personalities/), that receiv
18
16
19
17
Agents can cooperate to complete sequences of tasks through so-called [taskflows](doc/GRAMMAR.md).
20
18
21
-
You can find a detailed overview of the taskflow grammar [here](taskflows/GRAMMAR.md) and example taskflows [here](examples/taskflows/).
19
+
You can find a detailed overview of the taskflow grammar [here](doc/GRAMMAR.md) and example taskflows [here](examples/taskflows/).
22
20
23
21
## Use Cases and Examples
24
22
25
23
The Seclab Taskflow Agent framework was primarily designed to fit the iterative feedback loop driven work involved in Agentic security research workflows and vulnerability triage tasks.
26
24
27
25
Its design philosophy is centered around the belief that a prompt level focus of capturing vulnerability patterns will greatly improve and scale security research results as frontier model capabilities evolve over time.
28
26
29
-
While the maintainer himself primarily uses this framework as a code auditing toolit also serves as a more generic swiss army knife for exploring Agentic workflows. For example, the GitHub Security Lab also uses this framework for automated code scanning alert triage.
27
+
At GitHub Security Lab, we primarily use this framework as a code auditing tool, but it can also serve as a more generic swiss army knife for exploring Agentic workflows. For example, we also use this framework for automated code scanning alert triage.
30
28
31
29
The framework includes a [CodeQL](https://codeql.github.com/) MCP server that can be used for Agentic code review, see the [CVE-2023-2283](examples/taskflows/CVE-2023-2283.yaml) taskflow for an example of how to have an Agent review C code using a CodeQL database ([demo video](https://www.youtube.com/watch?v=eRSPSVW8RMo)).
32
30
33
31
Instead of generating CodeQL queries itself, the CodeQL MCP Server is used to provide CodeQL-query based MCP tools that allow an Agent to navigate and explore code. It leverages templated CodeQL queries to provide targeted context for model driven code analysis.
34
32
35
33
## Requirements
36
34
37
-
Python >= 3.9 or Docker
35
+
Python >= 3.10 or Docker
38
36
39
37
## Configuration
40
38
41
-
Provide a GitHub token for an account that is entitled to use [GitHub Models](https://models.github.ai) via the `AI_API_TOKEN` environment variable. Further configuration is use case dependent, i.e. pending which MCP servers you'd like to use in your taskflows.
39
+
Provide a GitHub token for an account that is entitled to use [GitHub Models](https://models.github.ai) via the `AI_API_TOKEN` environment variable. Further configuration is use case dependent, i.e. pending which MCP servers you'd like to use in your taskflows. In a terminal, you can add `AI_API_TOKEN` to the environment like this:
40
+
41
+
```sh
42
+
export AI_API_TOKEN=<your_github_token>
43
+
```
44
+
45
+
Or, if you are using GitHub Codespaces, then you can [add a Codespace secret](https://github.com/settings/codespaces/secrets/new) so that `AI_API_TOKEN` is automatically available when working in a Codespace.
42
46
43
-
You can set persisting environment variables via an `.env` file in the project root.
47
+
Many of the MCP servers in the [seclab-taskflow](https://github.com/GitHubSecurityLab/seclab-taskflows) repo also need an environment variable named `GH_TOKEN` for accessing the GitHub API. You can use two separate PATs if you want, or you can use one PAT for both purposes, like this:
48
+
49
+
```sh
50
+
export GH_TOKEN=$AI_API_TOKEN
51
+
```
52
+
53
+
We do not recommend storing secrets on disk, but you can persist non-sensitive environment variables by adding a `.env` file in the project root.
You can force certain tools within a `toolbox` to require user confirmation to run. This can be helpful if a tool may perform irreversible actions and should require user approval prior to its use. This is done by including the name of the tool (function) in the MCP server in the `confirm` section:
@@ -320,7 +328,7 @@ seclab-taskflow-agent:
320
328
321
329
taskflow:
322
330
- task:
323
-
# taskflows can optionally choose any of the support CAPI models for a task
331
+
# taskflows can optionally choose any of the models supported by your API for a task
324
332
model: gpt-4.1
325
333
# taskflows can optionally limit the max allowed number of Agent task loop
326
334
# iterations to complete a task, this defaults to 50 when not provided
@@ -339,7 +347,7 @@ taskflow:
339
347
Finally, why are apples and oranges healthy to eat?
340
348
341
349
# taskflows can set temporary environment variables, these support the general
342
-
# "{{ envFROM_EXISTING_ENVIRONMENT}" pattern we use elsewhere as well
350
+
# "{{ env('FROM_EXISTING_ENVIRONMENT') }}" pattern we use elsewhere as well
343
351
# these environment variables can then be made available to any stdio mcp server
344
352
# through its respective yaml configuration, see memcache.yaml for an example
345
353
# you can use these to override top-level environment variables on a per-task basis
@@ -386,7 +394,7 @@ taskflow:
386
394
387
395
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.
388
396
389
-
See the [taskflow examples](taskflows/examples) for other useful Taskflow patterns such as repeatable and asynchronous templated prompts.
397
+
See the [taskflow examples](examples/taskflows) for other useful Taskflow patterns such as repeatable and asynchronous templated prompts.
390
398
391
399
392
400
You can run a taskflow from the command line like this:
@@ -486,12 +494,12 @@ Files of types `taskflow` and `toolbox` allow environment variables to be passed
# prevent git repo operations on gh codeql executions
491
499
GH_NO_UPDATE_NOTIFIER: "disable"
492
500
```
493
501
494
-
For `toolbox`, `env` can be used inside `server_params`. A template of the form `{{ envENV_VARIABLE_NAME }}` can be used to pass values of the environment variable from the current process to the MCP server. So in the above, the MCP server is run with `GH_NO_UPDATE_NOTIFIER=disable` and passes the value of `CODEQL_DBS_BASE_PATH` from the current process to the MCP server. The templated paramater `{{ envCODEQL_DBS_BASE_PATH }}` is replaced by the value of the environment variable `CODEQL_DBS_BASE_PATH` in the current process.
502
+
For `toolbox`, `env` can be used inside `server_params`. A template of the form `{{ env('ENV_VARIABLE_NAME') }}` can be used to pass values of the environment variable from the current process to the MCP server. So in the above, the MCP server is run with `GH_NO_UPDATE_NOTIFIER=disable` and passes the value of `CODEQL_DBS_BASE_PATH` from the current process to the MCP server. The templated parameter `{{ env('CODEQL_DBS_BASE_PATH') }}` is replaced by the value of the environment variable `CODEQL_DBS_BASE_PATH` in the current process.
495
503
496
504
Similarly, environment variables can be passed to a `task` in a `taskflow`:
497
505
@@ -508,9 +516,9 @@ taskflow:
508
516
MEMCACHE_BACKEND: "dictionary_file"
509
517
```
510
518
511
-
This overwrites the environment variables `MEMCACHE_STATE_DIR` and `MEMCACHE_BACKEND` for the task only. A template `{{ envENV_VARIABLE_NAME }}` can also be used.
519
+
This overwrites the environment variables `MEMCACHE_STATE_DIR` and `MEMCACHE_BACKEND` for the task only. A template `{{ env('ENV_VARIABLE_NAME') }}` can also be used.
512
520
513
-
Note that when using the template `{{ envENV_VARIABLE_NAME }}`, `ENV_VARIABLE_NAME` must be the name of an environment variable in the current process.
521
+
Note that when using the template `{{ env('ENV_VARIABLE_NAME') }}`, `ENV_VARIABLE_NAME` must be the name of an environment variable in the current process.
Copy file name to clipboardExpand all lines: doc/GRAMMAR.md
+15-15Lines changed: 15 additions & 15 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -133,10 +133,10 @@ Often we may want to iterate through the same tasks with different inputs. For e
133
133
agents:
134
134
- seclab_taskflow_agent.personalities.c_auditer
135
135
user_prompt: |
136
-
The function has name {{ RESULT_name }} and body {{ RESULT_body }} analyze the function.
136
+
The function has name {{ result.name }} and body {{ result.body }} analyze the function.
137
137
```
138
138
139
-
In the above, the first task fetches functions in the code base and creates a json list object, with each entry having a `name` and `body` field. In the next task, `repeat_prompt` is set to true, meaning that a task is created for each individual object in the list and the object fields are referenced in the templated prompt using `{{ RESULT_<fieldname> }}`. In other words, `{{ RESULT_name }}` in the prompt is replaced with the value of the `name` field of the object etc. For example, if the list of functions fetched from the first task is:
139
+
In the above, the first task fetches functions in the code base and creates a json list object, with each entry having a `name` and `body` field. In the next task, `repeat_prompt` is set to true, meaning that a task is created for each individual object in the list and the object fields are referenced in the templated prompt using `{{ result.fieldname }}`. In other words, `{{ result.name }}` in the prompt is replaced with the value of the `name` field of the object etc. For example, if the list of functions fetched from the first task is:
140
140
141
141
```javascript
142
142
[{'name' : foo, 'body' : foo(){return 1;}}, {'name' : bar, 'body' : bar(a) {return a + 1;}}]
@@ -152,7 +152,7 @@ etc.
152
152
153
153
Note that when using `repeat_prompt`, the last tool call result of the previous task is used as the iterable. It is recommended to keep the task that creates the iterable short and simple (e.g. just make one tool call to fetch a list of results) to avoid wrong results being passed to the repeat prompt.
154
154
155
-
The iterable can also contain a list of primitives like string or number, in which case, the template `{{ RESULT }}` can be used in the `repeat_prompt` prompt to parse the results instead:
155
+
The iterable can also contain a list of primitives like string or number, in which case, the template `{{ result }}` can be used in the `repeat_prompt` prompt to parse the results instead:
156
156
157
157
```yaml
158
158
- task:
@@ -173,7 +173,7 @@ The iterable can also contain a list of primitives like string or number, in whi
173
173
agents:
174
174
- seclab_taskflow_agent.personalities.assistant
175
175
user_prompt: |
176
-
What is the integer value of {{ RESULT }}?
176
+
What is the integer value of {{ result }}?
177
177
```
178
178
179
179
Repeat prompt can be run in parallel by setting the `async` field to `true`:
@@ -185,7 +185,7 @@ Repeat prompt can be run in parallel by setting the `async` field to `true`:
185
185
agents:
186
186
- seclab_taskflow_agent.personalities.c_auditer
187
187
user_prompt: |
188
-
The function has name {{ RESULT_name }} and body {{ RESULT_body }} analyze the function.
188
+
The function has name {{ result.name }} and body {{ result.body }} analyze the function.
189
189
```
190
190
191
191
An optional limit can be set to limit the number of asynchronous tasks via `async_limit`. If not set, the default value (5) is used.
@@ -198,7 +198,7 @@ An optional limit can be set to limit the number of asynchronous tasks via `asyn
198
198
agents:
199
199
- seclab_taskflow_agent.personalities.c_auditer
200
200
user_prompt: |
201
-
The function has name {{ RESULT_name }} and body {{ RESULT_body }} analyze the function.
201
+
The function has name {{ result.name }} and body {{ result.body }} analyze the function.
202
202
```
203
203
204
204
Both `async` and `async_limit` have no effect when used outside of a `repeat_prompt`.
@@ -211,7 +211,7 @@ At the moment, we do not support nested `repeat_prompt`. So the following is not
211
211
agents:
212
212
- seclab_taskflow_agent.personalities.c_auditer
213
213
user_prompt: |
214
-
The function has name {{ RESULT_name }} and body {{ RESULT_body }} analyze the function.
214
+
The function has name {{ result.name }} and body {{ result.body }} analyze the function.
215
215
- task:
216
216
repeat_prompt: true
217
217
...
@@ -233,7 +233,7 @@ For example:
233
233
agents:
234
234
- seclab_taskflow_agent.personalities.assistant
235
235
user_prompt: |
236
-
What kind of fruit is {{ RESULT }}?
236
+
What kind of fruit is {{ result }}?
237
237
```
238
238
239
239
The string `["apple", "banana", "orange"]` is then passed directly to the next task.
@@ -349,7 +349,7 @@ taskflow:
349
349
agents:
350
350
- examples.personalities.fruit_expert
351
351
user_prompt: |
352
-
Tell me more about {{ GLOBALS_fruit }}.
352
+
Tell me more about {{ globals.fruit }}.
353
353
```
354
354
355
355
Global variables can also be set or overridden from the command line using the `-g` or `--global` flag:
@@ -422,10 +422,10 @@ A reusable taskflow can also have a templated prompt that takes inputs from its
422
422
agents:
423
423
- examples.personalities.fruit_expert
424
424
user_prompt: |
425
-
Tell me more about {{ INPUTS_fruit }}.
425
+
Tell me more about {{ inputs.fruit }}.
426
426
```
427
427
428
-
In this case, the template parameter `{{ INPUTS_fruit }}` is replaced by the value of `fruit` from the `inputs` of the user, which is apples in this case:
428
+
In this case, the template parameter `{{ inputs.fruit }}` is replaced by the value of `fruit` from the `inputs` of the user, which is apples in this case:
429
429
430
430
```yaml
431
431
- task:
@@ -437,9 +437,9 @@ In this case, the template parameter `{{ INPUTS_fruit }}` is replaced by the val
437
437
438
438
### Reusable Prompts
439
439
440
-
Reusable prompts are defined in files of `filetype` `prompts`. These are like macros that get replaced when a templated parameter of the form `{{ PROMPTS_<import-path> }}` is encountered.
440
+
Reusable prompts are defined in files of `filetype` `prompts`. These are like macros that get included using Jinja2's `{% include %}` directive.
441
441
442
-
Tasks can incorporate templated prompts which are then replaced by the actual prompt. For example:
442
+
Tasks can incorporate reusable prompts using the include directive. For example:
443
443
444
444
Example:
445
445
@@ -449,8 +449,8 @@ Example:
449
449
- examples.personalities.fruit_expert
450
450
user_prompt: |
451
451
Tell me more about apples.
452
-
453
-
{{ PROMPTS_examples.prompts.example_prompt }}
452
+
453
+
{% include 'examples.prompts.example_prompt' %}
454
454
```
455
455
and `examples.prompts.example_prompt` is the following:
0 commit comments