Nobubble
Nobubble•2mo ago

Unsafe assignment of an `any` value when working with Agents Component

Hey all, I might be doing something stupid here but whenever I USE (eg. return, map, reassign) the query data inside my createTool i get errors all over the place.
// 'patientCheckins' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.
const patientCheckins = await ctx.runQuery(api.checkins.getPatientCheckins, {
patientId: ctx.patientId,
});
// 'patientCheckins' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.
const patientCheckins = await ctx.runQuery(api.checkins.getPatientCheckins, {
patientId: ctx.patientId,
});
Whenever i just query and dont use the result (just logging or ignoring) there are no errors. The data is there, typed and all, and my entire app already works on that data. PS: Ive also noticed that ctx.auth.getUserIdentity returns nothing in Tools. Is that intentional because I would want to run some auth checks from the user thats calling it instead of giving the agent full access. Thnx in advance
8 Replies
Convex Bot
Convex Bot•2mo ago
Thanks for posting in <#1088161997662724167>. Reminder: If you have a Convex Pro account, use the Convex Dashboard to file support tickets. - Provide context: What are you trying to achieve, what is the end-user interaction, what are you seeing? (full error message, command output, etc.) - Use search.convex.dev to search Docs, Stack, and Discord all at once. - Additionally, you can post your questions in the Convex Community's <#1228095053885476985> channel to receive a response from AI. - Avoid tagging staff unless specifically instructed. Thank you!
Clever Tagline
Clever Tagline•2mo ago
This came up recently, and it's not specific to any component. See if the discussion in this thread helps: https://discord.com/channels/1019350475847499849/1424139486291427511
Nobubble
NobubbleOP•2mo ago
BTW its 'solved'ish when i do this, but that feels realllly wonky
type CheckinArray = Array<{
_id: Id<"checkins">;
_creationTime: number;
...etc
}>;
const patientCheckins: CheckinArray = await ctx.runQuery(internal.checkins.getPatientCheckinsInternal, {
patientId: ctx.patientId,
});
type CheckinArray = Array<{
_id: Id<"checkins">;
_creationTime: number;
...etc
}>;
const patientCheckins: CheckinArray = await ctx.runQuery(internal.checkins.getPatientCheckinsInternal, {
patientId: ctx.patientId,
});
Clever Tagline
Clever Tagline•2mo ago
If you're running a query from another query, I recommend going with the helper function approach referenced in that other thread. It's generally much cleaner to use that approach
Nobubble
NobubbleOP•2mo ago
Im running a query inside a tool though.. But thanks for your pointers ofc, i just dont understand why something so seamingly straightforward breaks convex' tight typescript generation and manually typing fixes it The solution you proposed works for calling in other queries etc, but it doesnt work inside a tool because the Toolctx doesnt have db on it. This below here works but it cant be the way they'd imagined it to work rite...
export type ToolCtxWithPatientId = ToolCtx & { patientId: string };

export const getPatientData = createTool({
args: z.object({
query: z.string().describe("Bla"),
}),
description:
"Bla",
handler: async (ctx: ToolCtxWithPatientId) => {
const patientCheckins = await getPatientCheckinsInternal(ctx);

return {
patientData: patientCheckins,
};
},
});

function getPatientCheckinsInternal(ctx: ToolCtxWithPatientId): Promise<Array<.......> {
return ctx.runQuery(internal.checkins.getPatientCheckinsInternal, {
patientId: ctx.patientId,
});
}
export type ToolCtxWithPatientId = ToolCtx & { patientId: string };

export const getPatientData = createTool({
args: z.object({
query: z.string().describe("Bla"),
}),
description:
"Bla",
handler: async (ctx: ToolCtxWithPatientId) => {
const patientCheckins = await getPatientCheckinsInternal(ctx);

return {
patientData: patientCheckins,
};
},
});

function getPatientCheckinsInternal(ctx: ToolCtxWithPatientId): Promise<Array<.......> {
return ctx.runQuery(internal.checkins.getPatientCheckinsInternal, {
patientId: ctx.patientId,
});
}
erquhart
erquhart•2mo ago
Yep, this is correct - typing the handler return breaks the circular inference loop. More here (expand the blue box): https://docs.convex.dev/functions/actions#dealing-with-circular-type-inference
Clever Tagline
Clever Tagline•2mo ago
Dang...I wish I knew earlier about that bit in the docs. 😅
erquhart
erquhart•2mo ago
I wish it was auto expanded, I think people miss it a lot of the time

Did you find this page helpful?