Configuration¶
The .coauthor.yml configuration file is essential for customizing the behavior of your Coauthor AI agent. It defines various tasks grouped into workflows, facilitating efficient process automation.
Modules¶
File Watcher¶
By default, the File Watcher will ignore certain folders such as __pycache__, .obsidian, and .git. You can customize this behavior in your .coauthor configuration file.
---
file-watcher:
ignore-folders: [__pycache__, .obsidian, .git]
Workflows¶
The workflows section consists of a list of workflows. Each workflow is uniquely identified by its name attribute in the configuration file. Workflows are collections of tasks executed in sequence when specific conditions, like changes in files or directories, are met.
Tasks¶
Tasks within the .coauthor.yml are defined using their id and type attributes. They perform distinct functions, from AI-based file modifications to regex-based updates. Below are some available task types:
AI Tasks¶
The ai task type employs AI to update a file based on specified configurations. To utilize this task, configure the OPENAI_API_URL and OPENAI_API_KEY environment variables. These variables ensure proper AI request authentication and routing.
id: A unique identifier for the task.type: Must be set toai.
Coauthor allows the flexibility to customize system and user prompts using the Jinja templating engine. Prompts are named system.md (required) and user.md (optional). Without a user prompt, the entire file is submitted as the user prompt. Prompts can be defined at both the workflow and task levels. Coauthor searches for prompts in the following order:
{workflow['name']}/{task['id']}/{filename}{workflow['name']}/{filename}{filename}
Prompt templates can be saved in the .coauthor/templates directory. You can modify the default Jinja settings by adding a jinja section in .coauthor.yml. For example:
jinja:
search_path: .coauthor/templates
custom_delimiters:
block_start_string: "{{{{%"
block_end_string: "%}}}}"
variable_start_string: "{{{{"
variable_end_string: "}}}}"
Regex Replace¶
This task type updates a file using regex pattern matching and substitution.
id: A unique identifier for the task.type: Set toregex_replace_in_file.
Write a File¶
This task writes content to a file, such as saving an AI task’s response.
id: A unique identifier for the task.type: Specifywrite_fileas the task type.content: The content to be written to the file.path: An optional path for the file to create or update. Without a specifiedpath, the path that triggered the workflow is used.
Both path and content support Jinja templating. For instance, the translation workflow shown below in the Hugo website example writes the AI task’s response to a different file using this feature.
PlantUML¶
This task converts PlantUML files to image formats like PNG and SVG using the PlantUML jar file.
Include a File¶
The include-file task type enables you to dynamically include the content of
external files into your documents. This is achieved by specifying a regex
pattern to locate the placeholder in the target document, with the file path for
inclusion captured by either the first capturing group or a named group path.
A customizable template allows you to define how the included content is represented in the document, ensuring consistency and flexibility. Consider the example configurations below that illustrate usage.
Basic Example¶
The following configuration illustrates using a regular expression where the file path to be included is captured by the first group.
workflows:
- name: include-files
path_patterns:
- .*\.md$
watch:
filesystem:
paths:
- content/en/
scan:
filesystem:
paths:
- content/en/
tasks:
- id: include-code-examples
type: include-file
dir: ../cka
regex: <!--\s*start-code-sample\s+([^ \t\n]+)\s*-->\s*(.*?)<!--\s*end-code-sample\s*-->
template: |
<!-- start-code-sample {{{{ task['include_file_path'] }}}} -->
```{{{{ task['include_file_path'] | extname }}}}
# {{{{ task['include_file_path'] }}}}
{{{{ task['include_file_content'] }}}}
```
<!-- end-code-sample -->
In practice, any markdown file with a placeholder like this:
<!-- start-code-sample ch02/rbac/build-observer-pod.yaml -->
<!-- end-code-sample -->
Will be replaced with:
<!-- start-code-sample ch02/rbac/build-observer-pod.yaml -->
```yaml
# ch02/rbac/build-observer-pod.yaml
# (Actual content of the YAML file is inserted here)
```
<!-- end-code-sample -->
Example Using Named Group path¶
Here is an example where the file path for inclusion is specified using a named capturing group.
workflows:
- name: include-files
path_patterns:
- .*\.md$
watch:
filesystem:
paths:
- content/en/
scan:
filesystem:
paths:
- content/en/
tasks:
- id: include-code-examples
type: include-file
dir: ../cka
regex: '(```(yaml|sh)\{[^\}]*data-src=\"(?P<path>[^\s\}]+)\"\})(.*?)```'
template: |
{{{{ task['match'][1] }}}}
# {{{{ task['include_file_path'] }}}}
{{{{ task['include_file_content'] }}}}
Now, by including the following in a markdown file:
```yaml{data-src="ch02/rbac/build-bot-serviceaccount.yaml"}
```
This will be expanded to:
```yaml{data-src="ch02/rbac/build-bot-serviceaccount.yaml"}
# ch02/rbac/build-bot-serviceaccount.yaml
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: build-bot
```
Example Using Named Groups and the indent Group¶
The example below illustrates how named capturing groups are utilized for
greater flexibility and control in include-file tasks. This approach leverages
groups like indent, which adds the ability to maintain consistent formatting
by preserving the original indentation level of included content, alongside
first_line for capturing the initiating line/configuration.
The enhancement allows you to apply an indentation captured by indent to the
included file content, ensuring consistent formatting across documents. In this
example, the indent group captures any leading spaces/tabs before the code
block’s starting line, using them when inserting the content, preserving
visually structured and aligned documents.
workflows:
- name: include-files
path_patterns:
- .*\.md$
watch:
filesystem:
paths:
- content/en/
scan:
filesystem:
paths:
- content/en/
tasks:
- id: include-code-examples
type: include-file
dir: ../cka
regex: '(?P<indent>[^\S\r\n]*)(?P<first_line>```(yaml|sh)\{[^\}]*data-src=\"(?P<path>[^\s\}]+)\"\})\n(?P<code_content>.*?)\n(?P=indent)```'
template: |
{{{{ task['match_groups']['first_line'] }}}}
# {{{{ task['include_file_path'] }}}}
{{{{ task['include_file_content'] }}}}
```
Now, by including the following in a markdown file:
```yaml{data-src="ch02/rbac/build-bot-serviceaccount.yaml"}
```
This will be expanded to:
```yaml{data-src="ch02/rbac/build-bot-serviceaccount.yaml"}
# ch02/rbac/build-bot-serviceaccount.yaml
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: build-bot
```
Replace Redirecting Links¶
The replace_redirecting_links task type is used to identify and update links that redirect to different URLs, preventing unnecessary redirection. This is useful in ensuring that links within your content point directly to the desired destination without intermediate steps.
For instance, you might have content with various https://oreil.ly links that redirect. Using this task type, you can provide a regular expression to capture these URLs. The task will then verify the links and replace them with their direct targets.
Example of its usage:
workflows:
- name: oreilly-links
path_patterns:
- .*\.md$
watch:
filesystem:
paths:
- content/en/
scan:
filesystem:
paths:
- content/en/
tasks:
- id: replace-redirect-links
type: replace_redirecting_links
regex: '"(https://oreil\.ly/[^\s"]+)"'
YouTube¶
The youtube task allows you to download a transcript and data of a YouTube
video. Which you can then process using the AI task.
workflows:
- name: youtube
path_patterns:
- .*\.md$
content_patterns:
- - .*@whatever:.*
- .*youtube_id:\s*(?P<video_id>\S+).*
watch:
filesystem:
paths:
- content/en/
tasks:
- id: youtube
type: youtube
- id: ai-update
type: ai
- id: write-file
type: write_file
content: >-
{{{{ config | get_task_attribute('ai-update', 'response') }}}}
Jira¶
The jira task enables Coauthor to monitor Jira issues for comments that require attention, such as questions directed at it. This requires a dedicated Jira user account for Coauthor, configured via the environment variables COAUTHOR_JIRA_USERNAME and COAUTHOR_JIRA_PASSWORD. Coauthor uses this account to poll for and respond to matching comments.
To trigger Coauthor, add a comment in Jira that matches one or more configured content patterns (regular expressions). For example, if COAUTHOR_JIRA_USERNAME is set to coauthor, mentioning @coauthor in a comment adds a tag like [~coauthor], which can be matched via regex.
The configuration must include the workflows[].watch.jira.url key. Here’s an example YAML configuration:
workflows:
- name: jira
content_patterns:
- '\[~coauthor\]'
watch:
jira:
url: https://jira.example.com
# query: # optional, default is 'updated >= -0.3h OR created >= -0.3h'
query: updated >= -0.35h OR created >= -0.35h
sleep: 10 # optional, default is 15 (seconds between polls)
tasks:
- id: ticket
type: ai
You must also provide system and user message templates in .coauthor/templates/jira/system.md and .coauthor/templates/jira/user.md. Here’s an example user template:
# User Message
## Jira Ticket Context
Ticket Type: {{ task['current-ticket'].fields.issuetype.name }}
Summary: {{ task['current-ticket'].fields.summary }}
Assignee: {{ task['current-ticket'].fields.assignee.name if task['current-ticket'].fields.assignee else 'Unassigned' }}
Status: {{ task['current-ticket'].fields.status.name }}
### Description
{{ task['current-ticket'].fields.description }}
### Comments
The following comments were added:
{% for comment in task['current-ticket'].fields.comment.comments %}
- **{{ comment.author.name }}** ({{ comment.created }}):
{{ comment.body }}
{% endfor %}
## Jira Comment
The following comment by user {{ task['current-comment'].author.name }} requires
your attention:
{{ task['current-comment'].body }}
Examples¶
Hugo Website Workflow Example¶
Coauthor can help maintain the Hugo-based community website for the C2 Platform c2platform.org. The .coauthor.yml configuration supports tasks like updating translations for Markdown files in the content/en/ directory. Setting the translate attribute to true triggers tasks such as ai-translate for content translation and write-file for outputting the result.
Below is an example configuration snippet:
jinja:
search_path: .coauthor/templates
custom_delimiters:
block_start_string: "{{{{%"
block_end_string: "%}}}}"
variable_start_string: "{{{{"
variable_end_string: "}}}}"
workflows:
- name: website
path_patterns:
- .*\.md$
content_patterns:
- ".*@ai-test:.*"
watch:
filesystem:
paths:
- content/en/
scan:
filesystem:
paths:
- content/en/
tasks:
- id: ai-update
type: ai
- id: write-file
type: write_file
content: >-
{{{{ config | get_task_attribute('ai-update', 'response') }}}}
- name: hugo
path_patterns:
- layouts\/.*\.html$
content_patterns:
- ".*@ai-test:.*"
watch:
filesystem:
paths:
- layouts
tasks:
- id: ai-update
type: ai
- id: write-file
type: write_file
content: >-
{{{{ config | get_task_attribute('ai-update', 'response') }}}}
- name: translation
path_patterns:
- .*\.md$
content_patterns:
- ".*translate: true.*"
watch:
filesystem:
paths:
- content/en/
scan:
filesystem:
paths:
- content/en/
tasks:
- id: ai-translate
type: ai
- id: write-file
type: write_file
content: >-
{{{{ config | get_task_attribute('ai-translate', 'response') }}}}
path: >-
{{{{ config['current-task']['path-modify-event']
| replace('content/en', 'content/nl') }}}}
- id: translate-false
type: regex_replace_in_file
patterns:
- regex: "translate: true"
replace: "translate: false"
- name: regex-file-updates
path_patterns:
- .*\.md$
watch:
filesystem:
paths:
- content/en/
tasks:
- id: regex-file-updates
type: regex_replace_in_file
patterns:
- regex: ({{< \b[\s\S]*?>}})
internal_regex: \s+
internal_replace: ' '
- regex: "(?<!` ) -> "
replace: " → "
- regex: "(?<!` ) <- "
replace: " ← "
- regex: \[([^\]]+)\]\(http://localhost:1313([^\)]+?)/\)
replace: '{{< rellink path="\2" >}}'
Following this configuration, Coauthor effectively manages tasks such as translations, file writing, and regex-based transformations, thereby streamlining website management and content automation.