Skip to content

Use case

Expense Upload & Approval Widget ​

Let employees upload receipts, extract fields, and submit expense requests through a Studio-powered finance widget embedded in your product.

  • Stack Client SDK
  • Pattern Chat · Widget
  • Read ~6 min

Overview ​

Expense submission is a strong AI widget scenario because users need both conversation and action. They ask what is reimbursable, upload a receipt, confirm extracted values, and then submit the request into the finance workflow.

With Client SDK, the peer stays inside Studio while your app handles device access, file picking, OCR fallbacks, and workflow submission.

When to reach for this use case

If your team needs the capabilities described above and you would rather build on proven primitives than wire one from scratch — this is the shape to start from.

Architecture ​

Client SDK is the integration surface. The widget sits in your employee app, while a Studio peer handles guidance, follow-up questions, and structured tool selection.

Client tools bridge the conversation with product actions such as opening the camera, selecting a receipt from storage, calling your OCR service, or submitting the expense to ERP.

1. Add Receipt And Submission Tools ​

Expose only the actions your app can safely execute on behalf of the signed-in employee.

typescript
const expenseTools = [
  {
    type: 'function',
    function: {
      name: 'pickReceiptFromDevice',
      description: 'Open the native file picker and return the selected receipt metadata',
      parameters: {
        type: 'object',
        properties: {},
      },
    },
    implementation: async () => {
      const receipt = await openReceiptPicker();
      return JSON.stringify(receipt);
    },
  },
  {
    type: 'function',
    function: {
      name: 'createExpenseDraft',
      description: 'Create a draft expense request in the finance system',
      parameters: {
        type: 'object',
        properties: {
          merchant: { type: 'string' },
          amount: { type: 'number' },
          currency: { type: 'string' },
          category: { type: 'string' },
        },
        required: ['merchant', 'amount', 'currency', 'category'],
      },
    },
    implementation: async (payload) => {
      const response = await fetch('/api/expenses/draft', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      });

      return JSON.stringify(await response.json());
    },
  },
];

2. Let The Peer Drive The Submission Flow ​

The peer can ask clarifying questions, call the right tools, and continue the flow after each tool result.

typescript
const response = await client.conversations.create({
  messages: [
    {
      role: 'user',
      content: 'I need to upload my taxi receipt from the airport and submit it as a travel expense.',
    },
  ],
  clientTools: expenseTools,
});

if (response.tools?.length) {
  console.log('Executed tools:', response.tools.map((tool) => tool.name));
}

console.log(response.content);

Result ​

You get a finance widget that:

  • Guides employees during receipt submission
  • Uses native file picker or camera access through client tools
  • Creates structured expense drafts in your own workflow backend
  • Avoids rebuilding peer logic separately for web and mobile experiences

Products used ​

This pattern is built on one Cognipeer product.

The peer itself is authored and maintained in Cognipeer Studio — the SDK only connects your product to it.

See every pattern on the use case index, or browse all Cognipeer libraries.

Studio · Pulse · Console · Agent SDK and more — the Cognipeer documentation hub