::title::
Yusuke Wada
Cloudflare Workers実践LT 〜移行から運用、コストの話まで〜 ・ September 24, 2026
::right::

::center::
Jev!!
::center::
JevRouterを作った話
hono-jev-routerimport { PatternRouter } from 'hono/router/pattern-router'
const app = new Hono({
router: new PatternRouter()
})
import { Hono } from 'hono'
import { JevRouter } from 'hono-jev-router'
const app = new Hono({
router: new JevRouter()
})
app.on('jev', 'AIエージェントからのリクエストだよ', (c) => {
return c.text('# Documentation', 200, { 'Content-Type': 'text/markdown' })
})
app.on('jev', '人間からのリクエストだよ', (c) => {
return c.html('<h1>Documentation</h1>')
})
app.on('jev', '自動化されたアクセスだよ', (c) => {
return c.text('Forbidden', 403)
})
{
"state": {
"method": "GET",
"url": "https://example.com/docs",
"headers": {
"user-agent": "claude-code/2.0",
"accept": "text/markdown",
"cookie": "[redacted]"
}
},
"questions": {
"route_1": {
"type": "noul",
"instructions": "A router has a handler for requests described as \"AIエージェントからのリクエストだよ\". Is this HTTP request one that the handler should receive?"
}
}
}
{
"answers": {
"route_1": { "noul": 0.94 },
"route_2": { "noul": 0.2 },
"route_3": { "noul": 0.05 }
}
}
::center::
デモ
-# https://hono-jev-router.yusuke.run
npx hono request /docs -H 'user-agent: claude-code/2.0' -H 'accept: text/markdown'
npx hono request /docs -H 'user-agent: Mozilla/5.0 (Macintosh) Safari/605.1' -H 'accept: text/html'
npx hono request /docs -H 'user-agent: python-requests/2.31' -H 'accept: */*'
npx hono request /support -X POST \
-d '先月の請求額が2回引き落とされてるみたいなんですが、確認できますか?'
npx hono request /support -X POST \
-d 'もう使わないので解約したいです。手続きを教えてください。'
npx hono request /support -X POST \
-d '3回問い合わせてるのに返事がない。いい加減にしてください。今すぐ対応して。'
npx hono request /support -X POST \
-d 'ダークモードって対応予定ありますか?'
import { createMiddleware } from 'hono/factory'
export const jevMiddleware = (question: string, threshold = 0.8) =>
createMiddleware(async (c, next) => {
const state = await c.req.text()
const res = await c.env.AI.run('typesafe/jev', {
state,
questions: { flag: { type: 'noul', instructions: question } }
})
const p = (res.result ?? res).answers.flag.noul
if (p > threshold) {
return c.json({ blocked: true, probability: p }, 400)
}
await next()
})
import { Hono } from 'hono'
import { jevMiddleware } from './middleware'
const app = new Hono()
app.post('/comments', jevMiddleware('これはスパムですか?'), (c) => {
return c.json({ posted: true })
})
export default app
npx hono request -X POST -d "副業で月収100万円!スマホだけで誰でも簡単!今すぐLINE登録" /comments ./src/using-middleware.ts