AI-powered support draft bot for Pylon. Receives Pylon webhooks, generates draft replies using Claude (via Kilo Gateway), and posts them as internal notes on the Pylon issue for human review.
Rendering mermaid diagram...
Add these environment variables in the Val Town project settings:
| Key | Description | Where to get it |
|---|---|---|
KILO_GATEWAY_KEY | Kilo Gateway API key | app.kilo.ai/profile |
PYLON_API_KEY | Pylon API token (Bearer auth) | Pylon → Settings → API → Create token |
PYLON_WEBHOOK_SECRET | Webhook destination secret | Pylon → Settings → API → Webhook destination secret |
- Go to Pylon → Settings → API → Webhooks.
- Create a new webhook destination with URL:
https://YOUR-VAL-ENDPOINT.web.val.run/ - Select the event types you want to trigger on (e.g.,
issue.message.created). - Save the secret — add it as
PYLON_WEBHOOK_SECRETin Val Town.
Create a Pylon Trigger that fires on new customer messages and sends a webhook with the issue ID:
{ "id": "{{issue.id}}" }
The bot will fetch the full issue context (metadata and conversation history) from the Pylon API.
| File | Purpose |
|---|---|
main.ts | HTTP handler — webhook receiver, signature verification, background processing |
pylon.ts | Pylon API client — webhook verification, context fetching, note posting |
pipeline.ts | Core pipeline — fetch context → generate LLM reply → post note |
prompt.md | System prompt for the AI model with response guidelines |
scripts/test-pipeline.ts | End-to-end test script |
README.md | This file |
- Webhook received at
POST /— the handler verifies the Pylon HMAC-SHA256 signature. - Early return — responds
200 OKimmediately, then fires a background request toPOST /process. - Fetch context — retrieves full issue metadata and conversation history from Pylon API.
- AI inference — loads
prompt.mdas the system prompt, sends the issue context to Claude Opus 4.6 via Kilo Gateway. - Internal note — posts the AI-generated draft as an internal-only note on the Pylon issue.
- Error handling — on failure, sends an error notification email to
steve@val.town.
Edit pipeline.ts to use a different model:
// Current: Claude Opus 4.6 via Kilo Gateway
const kilo = createOpenAI({
baseURL: "https://api.kilo.ai/api/gateway",
apiKey: Deno.env.get("KILO_GATEWAY_KEY"),
});
const { text: draftReply } = await generateText({
model: kilo("anthropic/claude-opus-4-6"),
system: systemPrompt,
prompt: userPrompt,
});
// Example: Use a different model through Kilo Gateway
const { text: draftReply } = await generateText({
model: kilo("openai/gpt-4-turbo"),
system: systemPrompt,
prompt: userPrompt,
});
Edit prompt.md to add:
- Product-specific knowledge
- FAQ pairs from your support history
- Links to your documentation
- Custom tone and style guidelines
- Troubleshooting trees for common issues
Run the test script to verify the pipeline end-to-end:
// Edit scripts/test-pipeline.ts with a real issue ID
const TEST_ISSUE_ID = "your-pylon-issue-id";
// Run the script from Val Town
The bot verifies Pylon webhook signatures using HMAC-SHA256:
- Pylon sends
X-Pylon-Signatureheader with hex-encoded digest - Bot computes HMAC-SHA256 of raw request body using
PYLON_WEBHOOK_SECRET - Constant-time comparison prevents timing attacks
- Invalid signatures return
401 Unauthorized
See Pylon webhook signature docs for more details.
GET /issues/{id}— Fetch issue metadataGET /issues/{id}/messages— Fetch conversation messages (with pagination)POST /issues/{id}/threads— Create a new threadPOST /issues/{id}/note— Post an internal note to a thread
See Pylon API Reference for more details.
This bot is deployed on Val Town, a serverless platform for TypeScript/JavaScript functions.
To deploy your own:
- Fork this val or create a new val in your Val Town account
- Add the required environment variables (see Setup section)
- Configure the Pylon webhook destination to point to your val's endpoint
- Test with a real issue using
scripts/test-pipeline.ts