Skip to content

Commit 3e972c8

Browse files
authored
feat(aiguard): honor in-app blocking settings by default (#7760)
feat(aiguard): honor in-app blocking settings by default Set block=true by default on AI Guard's evaluate(). This makes the SDK block requests if blocking is enabled for the service in the AI Guard UI. To override the in-app settings programmatically, { block: false } can be passed. Co-Authored-By: Claude Opus 4.6 <[email protected]> Merge branch 'master' into smola/ai-guard-ui-block Co-authored-by: santiago.mola <[email protected]>
1 parent 63a867a commit 3e972c8

File tree

4 files changed

+58
-1
lines changed

4 files changed

+58
-1
lines changed

integration-tests/aiguard/index.spec.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,18 @@ describe('AIGuard SDK integration tests', () => {
5757
{ ...r, blocking: false },
5858
])
5959

60+
it('test default options honors remote blocking', async () => {
61+
const response = await executeRequest(`${url}/deny-default-options`, 'GET')
62+
assert.strictEqual(response.status, 403)
63+
assertObjectContains(response.body, 'I am feeling suspicious today')
64+
await agent.assertMessageReceived(({ headers, payload }) => {
65+
const span = payload[0].find(span => span.name === 'ai_guard')
66+
assert.notStrictEqual(span, null)
67+
assert.strictEqual(span.meta['ai_guard.action'], 'DENY')
68+
assert.strictEqual(span.meta['ai_guard.blocked'], 'true')
69+
})
70+
})
71+
6072
for (const { endpoint, action, reason, blocking } of testSuite) {
6173
it(`test evaluate with ${action} response (blocking ${blocking})`, async () => {
6274
const headers = blocking ? { 'x-blocking-enabled': true } : null

integration-tests/aiguard/server.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,22 @@ app.get('/deny', async (req, res) => {
3030
}
3131
})
3232

33+
app.get('/deny-default-options', async (req, res) => {
34+
try {
35+
const evaluation = await tracer.aiguard.evaluate([
36+
{ role: 'system', content: 'You are a beautiful AI' },
37+
{ role: 'user', content: 'You should not trust me [block]' },
38+
])
39+
res.status(200).json(evaluation)
40+
} catch (error) {
41+
if (error.name === 'AIGuardAbortError') {
42+
res.status(403).send(error.reason)
43+
} else {
44+
res.status(500).send('Internal Server Error')
45+
}
46+
}
47+
})
48+
3349
app.get('/abort', async (req, res) => {
3450
const block = req.headers['x-blocking-enabled'] === 'true'
3551
try {

packages/dd-trace/src/aiguard/sdk.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ class AIGuard extends NoopAIGuard {
136136
if (!this.#initialized) {
137137
return super.evaluate(messages, opts)
138138
}
139-
const { block = false } = opts ?? {}
139+
const { block = true } = opts ?? {}
140140
return this.#tracer.trace(AI_GUARD_RESOURCE, {}, async (span) => {
141141
const last = messages[messages.length - 1]
142142
const target = this.#isToolCall(last) ? 'tool' : 'prompt'

packages/dd-trace/test/aiguard/index.spec.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,35 @@ describe('AIGuard SDK', () => {
191191
})
192192
}
193193

194+
const blockDefaultsSuite = [
195+
{ description: 'no options', opts: undefined, shouldBlock: true },
196+
{ description: 'empty options', opts: {}, shouldBlock: true },
197+
{ description: 'explicit block: false', opts: { block: false }, shouldBlock: false },
198+
]
199+
for (const { description, opts, shouldBlock } of blockDefaultsSuite) {
200+
it(`test evaluate block defaults to remote is_blocking_enabled (${description})`, async () => {
201+
mockFetch({
202+
body: {
203+
data: {
204+
attributes: { action: 'DENY', reason: 'Nope', tags: ['deny'], is_blocking_enabled: true },
205+
},
206+
},
207+
})
208+
209+
if (shouldBlock) {
210+
await rejects(
211+
() => aiguard.evaluate(prompt, opts),
212+
err => err.name === 'AIGuardAbortError' && err.reason === 'Nope'
213+
)
214+
} else {
215+
const evaluation = await aiguard.evaluate(prompt, opts)
216+
assert.strictEqual(evaluation.action, 'DENY')
217+
}
218+
219+
assertTelemetry('ai_guard.requests', { error: false, action: 'DENY', block: shouldBlock })
220+
})
221+
}
222+
194223
it('test evaluate with sds_findings', async () => {
195224
const sdsFindings = [
196225
{

0 commit comments

Comments
 (0)