Send emails and collect responses via email threads
Configuration
The Email contact channel allows agents to send emails and collect responses through email threads.
Configure an email channel using the EmailContactChannel
model:
Email Address
The address
field must be a valid email address that will receive the messages.
Context
The optional context_about_user
field helps the LLM understand who it’s emailing:
Usage
Use the email channel with either require_approval
or human_as_tool
features:
Or you can pass the contact_channel
to the HumanLayer
instance:
If you pass a channel to the HumanLayer
instance, you don’t need to pass it to the require_approval
or human_as_tool
features.
If you pass it to both, the channel in the require_approval
or human_as_tool
will take precedence.
Custom Email Templates
You can provide custom Jinja2 templates to fully control the email body HTML. The template type is automatically detected based on whether it’s used with require_approval
or human_as_tool
.
Function Call Template Example
For function calls that need approval, your template has access to the function name, arguments, and approval actions:
Human Contact Template Example
For human-as-tool contacts, your template has access to the message and response options:
Template Variables
Both types of templates receive these variables:
event
- The full event object (function call or human contact)urls.base_url
- The URL for approval/response actionstype
- Either “v1beta2.function_call” or “v1beta2.human_contact”
If no template is provided, the default HumanLayer email template is used.
For a complete TypeScript example of email templates, see the email templates example.
Email Threading
By default, every human contact or function call will trigger a new standalone email thread.
However, if you’re building agents that are kicked off by email runs, you likely want the email responses to be collected in a single thread.
You can do this by using the in_reply_to_message_id
and references_message_id
parameters
to the EmailContactChannel, using the inbound email’s Message-ID
header as the value.
Below is an example where the inbound email is sent by the same human who will be responding to approval/human_as_tool requests.
You can also use the helper method EmailContactChannel.in_reply_to()
to create a channel that replies to an existing email: