Write File functions allow AI assistants to create or overwrite files with content, using built-in security controls that restrict access to designated directories.
Caution: File Overwrite Write File functions will overwrite existing files without warning. Use Edit File functions for safer modifications to existing files.
Configuration
function :
type : write_file
path : "{{ filename }}"
content : "{{ file_content }}"
Path to the file to write. Can be absolute or relative to the working directory (config/extended_openai_conversation/).
Content to write to the file. Can include Jinja2 templates for dynamic content generation.
Optional list of additional allowed directories (as templates). By default, only the working directory is allowed.
Working Directory
The default working directory is config/extended_openai_conversation/.
Relative Path
Subdirectory
Absolute Path
# Writes to /config/extended_openai_conversation/notes.txt
function :
type : write_file
path : "notes.txt"
content : "{{ note_text }}"
# Writes to /config/extended_openai_conversation/data/config.json
# Note: Parent directory must already exist
function :
type : write_file
path : "data/config.json"
content : "{{ json_data }}"
# Writes to /config/scripts/generated.py
function :
type : write_file
path : "/config/scripts/generated.py"
content : "{{ python_code }}"
Examples
Write File
- spec :
name : write_file
description : Write content to a file in workspace.
parameters :
type : object
properties :
filename :
type : string
description : Name of the file
content :
type : string
description : Content to write
required :
- filename
- content
function :
type : write_file
path : "{{ filename }}"
content : "{{ content }}"
Custom Allowed Directories
Extend allowed directories beyond the default workspace. The allow_dir parameter adds additional directories where files can be written.
- spec :
name : write_file_with_allow_dir
description : Write a file with custom allowed directories.
parameters :
type : object
properties :
filename :
type : string
description : Name of the file
content :
type : string
description : Content to write
required :
- filename
- content
function :
type : write_file
path : "{{ filename }}"
content : "{{ content }}"
allow_dir :
- "/backup"
- "/media"
allow_dir accepts templates with access to variables like {{ config_dir }}:allow_dir :
- "{{ config_dir }}/www"
- "{{ config_dir }}/custom_data"
Return Value
On success:
{
"success" : true ,
"path" : "/config/extended_openai_conversation/notes.txt" ,
"bytes_written" : 1234
}
On error:
{
"error" : "Access denied: path 'filename' is not in allowed directories"
}
Error Types
Access denied : File path is outside allowed directories
Permission error : Insufficient permissions to write file
No such file or directory : Parent directory doesn’t exist
Other errors : Encoding issues, disk full, etc.
Dynamic Content Generation
Write File functions support Jinja2 templates in the content field:
Generate YAML Configuration
- spec :
name : create_automation
description : Create a new automation configuration
parameters :
type : object
properties :
automation_name :
type : string
trigger_entity :
type : string
action_entity :
type : string
function :
type : write_file
path : "automations/{{ automation_name | slugify }}.yaml"
content : |
- alias: "{{ automation_name }}"
trigger:
- platform: state
entity_id: {{ trigger_entity }}
action:
- service: homeassistant.turn_on
target:
entity_id: {{ action_entity }}
Generate JSON Data
- spec :
name : save_sensor_data
description : Save sensor data to JSON file
parameters :
type : object
properties :
sensor_id :
type : string
readings :
type : array
items :
type : number
function :
type : write_file
path : "data/{{ sensor_id }}.json"
content : |
{
"sensor": "{{ sensor_id }}",
"timestamp": "{{ now().isoformat() }}",
"readings": {{ readings | tojson }}
}
Generate Python Script
- spec :
name : create_python_script
description : Create a Python script for automation
parameters :
type : object
properties :
script_name :
type : string
entity_id :
type : string
function :
type : write_file
path : "python_scripts/{{ script_name }}.py"
content : |
# Generated script: {{ script_name }}
# Created: {{ now().strftime('%Y-%m-%d %H:%M:%S') }}
entity_id = "{{ entity_id }}"
state = hass.states.get(entity_id)
if state and state.state == "on":
logger.info(f"{entity_id} is on")
Use Cases
Note Taking Save user notes, reminders, and documentation
Configuration Generation Generate automation configs, scripts, templates
Data Export Export sensor data, logs, or analysis results
Report Generation Create markdown, CSV, or text reports
Common Patterns
Append Timestamp to Filename
- spec :
name : save_log
description : Save log entry with timestamp
parameters :
type : object
properties :
log_message :
type : string
function :
type : write_file
path : "logs/{{ now().strftime('%Y%m%d_%H%M%S') }}.log"
content : |
[{{ now().strftime('%Y-%m-%d %H:%M:%S') }}] {{ log_message }}
Write Multiple Lines
- spec :
name : write_todo_list
description : Write a todo list
parameters :
type : object
properties :
tasks :
type : array
items :
type : string
function :
type : write_file
path : "todo.txt"
content : |
# Todo List - {{ now().strftime('%Y-%m-%d') }}
{% for task in tasks %}
- [ ] {{ task }}
{% endfor %}
Write CSV Data
- spec :
name : export_to_csv
description : Export data to CSV
parameters :
type : object
properties :
filename :
type : string
headers :
type : array
items :
type : string
rows :
type : array
items :
type : array
function :
type : write_file
path : "exports/{{ filename }}.csv"
content : |
{{ headers | join(',') }}
{% for row in rows %}
{{ row | join(',') }}
{% endfor %}
Conditional Content
- spec :
name : write_status_report
description : Write system status report
parameters :
type : object
properties :
system_ok :
type : boolean
errors :
type : array
items :
type : string
function :
type : write_file
path : "reports/status_{{ now().strftime('%Y%m%d') }}.md"
content : |
# System Status Report
**Date**: {{ now().strftime('%Y-%m-%d %H:%M:%S') }}
**Status**: {% if system_ok %}✅ All systems operational{% else %}⚠️ Issues detected{% endif %}
{% if not system_ok and errors %}
## Errors
{% for error in errors %}
- {{ error }}
{% endfor %}
{% endif %}
Security
Files must be within allowed directories. By default:
/config/extended_openai_conversation/ (working directory)
Additional directories can be added via allow_dir.
Path Traversal Protection
Paths are resolved to absolute paths and validated. Attempts to use ../ to escape allowed directories will be blocked.
Write File overwrites existing files without confirmation. Use Edit File for safer modifications.
Parent directories are not automatically created. The parent directory must exist before writing a file. Use bash functions if you need to create directories: type : composite
sequence :
- type : bash
command : "mkdir -p data/reports"
- type : write_file
path : "data/reports/report.txt"
content : "{{ content }}"
Best Practices
Validate before overwriting
Check if file exists before overwriting (use composite function): type : composite
sequence :
- type : bash
command : "test -f {{ filename }} && echo 'exists' || echo 'new'"
response_variable : file_status
- type : template
value_template : |
{% if 'exists' in file_status.stdout %}
Error: File already exists. Use edit_file or choose a different name.
{% else %}
{# Proceed with write #}
{% endif %}
Use descriptive filenames
Include timestamps or identifiers in filenames: path : "backups/{{ entity_id }}_{{ now().strftime('%Y%m%d_%H%M%S') }}.json"
Handle encoding properly
Always use UTF-8 text. For special characters, ensure proper escaping: content : |
# Content with special characters
Temperature: {{ temp }}°C
Status: {{ status | replace('"', '\\"') }}
Organize files in subdirectories
Use subdirectories to organize files (ensure they exist first): path : "logs/{{ now().strftime('%Y/%m') }}/{{ filename }}.log"
Troubleshooting
Access denied: path not in allowed directories
The target path is outside allowed directories. Either:
Write to the workspace (/config/extended_openai_conversation/)
Add the target directory to allow_dir
No such file or directory
The parent directory doesn’t exist. Create it first: type : composite
sequence :
- type : bash
command : "mkdir -p $(dirname '{{ filepath }}')"
- type : write_file
path : "{{ filepath }}"
content : "{{ content }}"
Check:
File permissions on the parent directory
Available disk space
SELinux or AppArmor policies (in container environments)
FAQ
What happens to existing files?
Existing files are overwritten without warning. There is no backup or confirmation. Use Edit File for safer modifications to existing files.
Are parent directories created automatically?
No. Parent directories must exist before writing a file. Use bash functions to create directories if needed.
What's the maximum file size I can write?
There’s no explicit limit, but very large content (>10MB) may cause memory issues. For large files, consider using bash functions with streaming: type : bash
command : "cat > {{ filename }} << 'EOF' \n {{ content }} \n EOF"
Can I append to existing files?
No. Write File always overwrites. To append, use bash functions: type : bash
command : "echo '{{ new_line }}' >> {{ filename }}"
Next Steps