Skip to content

Repository files navigation

CROO Provider — Invoice Analyzer Agent

An autonomous CROO Agent Protocol (CAP) provider that turns receipts and invoices (images, PDFs, ZIPs, or shared cloud-folder links) into clean, accounting-ready exports — Excel / CSV / JSON for JP / US / UK / AU, plus QuickBooks and Xero formats. Buyers call the agent on-chain, pay in USDC on Base, and receive structured, downloadable outputs back through CROO.

CROO Agent Hackathon submission — track: Tools for other CAP builders / Data & Verification Agents.

Live on the CROO Agent Store: https://agent.croo.network/agents/773d1bcf-a2e2-411a-a685-b1b550ead75c

License: MIT CROO SDK


Table of contents


What it does

This agent runs as a long-lived CROO provider. It listens for on-chain negotiations and paid orders over the CROO WebSocket, executes the requested service, and delivers the results back to the buyer. It exposes four services:

Service Purpose
echo_test Connectivity / health check for the CAP round trip.
invoice_analyze One-shot: submit files, get structured invoice data + exports.
invoice_agent_analyze Analyze with agent-style parameter resolution.
invoice_agent_chat Conversational — keeps history, asks for missing info, then runs the job.

Under the hood the provider forwards work to an Azure Functions Invoice Analyzer backend (create job → poll → fetch outputs), then mirrors the output files into CROO storage so buyers get stable download links instead of short-lived SAS URLs.


Hackathon submission checklist

Replace the placeholders above with your live links before final submission.


Architecture

CROO (buyer + on-chain settlement)
        │  negotiation / order events (WebSocket)
        ▼
Provider Container (this repo, @croo-network/sdk)
        │  create job → poll status → get outputs
        ▼
Azure Functions Invoice Analyzer
        │  standardized outputs (Excel / CSV / JSON)
        ▼
Provider mirrors outputs → CROO storage → delivered to buyer

Source layout:

  • src/index.ts — CROO connection, event subscription, order lifecycle, delivery.
  • src/config.ts — environment-variable validation (zod).
  • src/clients/invoiceAnalyzerClient.ts — Azure Functions Invoice API client.
  • src/clients/azureOpenAiClient.ts — Azure OpenAI / Foundry Responses API client.
  • src/services/conversationStore.ts — conversation state store (memory / Azure table).
  • src/services/slotFillingService.ts — intent detection and slot filling.
  • src/handlers/invoiceAnalyzeHandler.ts — direct (one-shot) handler.
  • src/handlers/invoiceAgentChatHandler.ts — conversational agent handler.
  • src/types/* — shared type definitions.
  • src/utils/outputFormats.ts — per-country default output formats.
  • scripts/* — local test harnesses (see Local testing).

CROO / CAP integration (SDK methods used)

The provider is built entirely on @croo-network/sdk. Key methods used (src/index.ts):

Connect & subscribe

const client = new AgentClient(
  { baseURL: CROO_API_URL, wsURL: CROO_WS_URL, logger },
  CROO_API_KEY,
);

const stream = await client.connectWebSocket();
stream.on(EventType.NegotiationCreated, handleNegotiationCreated);
stream.on(EventType.OrderPaid, handleOrderPaid);
stream.onAny(logEvent);

Order lifecycle

SDK method Used for
client.acceptNegotiation(negotiationId) Accept an incoming negotiation for a supported service.
client.getOrder(orderId) Read the paid order details.
client.getNegotiation(negotiationId) Resolve the negotiated service + requirements.
client.deliverOrder(orderId, deliverable) Deliver the result back to the buyer.
client.uploadFile(fileName, buffer) Upload output files into CROO storage.
client.getDownloadURL(objectKey) Get a stable CROO download URL for delivery.
client.listNegotiations({ ... }) Reconcile pending negotiations on reconnect.
client.listOrders({ ... }) Reconcile paid-but-undelivered orders on reconnect.

Reliability: a background reconciler periodically calls listNegotiations / listOrders so no negotiation or paid order is missed if the WebSocket drops. Negotiation-accept and order-processing are idempotent and guarded with in-flight sets to avoid double-processing.


Services offered

The set of supported services is defined in SUPPORTED_SERVICES (src/index.ts): echo_test, invoice_analyze, invoice_agent_analyze, invoice_agent_chat.

Incoming CROO service_ids are mapped to internal service names via CROO_SERVICE_ID_MAP, with an optional CROO_DEFAULT_SERVICE fallback.


Agent chat mode (invoice_agent_chat)

invoice_agent_chat is a stateful, conversational flow:

  • Receives a natural-language message.
  • Restores conversation state when a conversationId is supplied.
  • Merges slots: countryHint, outputFormats, inputFiles.
  • Detects intent with Azure OpenAI, falling back to a rule-based parser.
  • If information is missing:
    • returns status=needs_input
    • returns questions and missingFields
    • the caller resends the same conversationId with the answer
  • Only when all required info is present:
    • createJob → waitForJobCompletion → getJobOutputs
    • returns status=completed

Shared cloud links are supported and pre-validated before a job is submitted:

  • Auto-retries common share links (SharePoint/OneDrive download=1, Google Drive direct-download conversion, iCloud download=1).
  • SharePoint/OneDrive folder links (/:f:/...) expand supported files (PDF/JPG/PNG/TIFF/HEIC/ZIP), up to 50 files.
  • Google Drive folder links (/drive/folders/...) expand recursively, up to 50 files.
  • iCloud Drive folder links (/iclouddrive/...) expand public files, up to 50 files.
  • If a link cannot be fetched, the flow returns needs_input and keeps the conversation open.

Key contract details

Constraints enforced against the Azure Functions backend:

  • countryHint accepts only JP | US | UK | AU | AUTO (note: UK is UK, not GB).
  • outputFormats accepts only: standard_excel, standard_csv, universal_json, japan_expense_excel, quickbooks_csv, xero_csv.
  • Each inputFiles entry requires either sourceUrl or contentBase64.
  • If outputFormats is empty, the backend defaults to standard_excel, standard_csv, universal_json.
  • For JP/US/UK/AU extended exports, specify outputFormats explicitly on the provider side.

Environment variables

Copy .env.example to .env and fill in values.

Required

  • CROO_API_URL
  • CROO_WS_URL
  • CROO_API_KEY (recommended)
  • CROO_SDK_KEY (legacy fallback; used only when CROO_API_KEY is unset)
  • INVOICE_API_BASE_URL
  • INVOICE_CREATE_JOB_KEY
  • INVOICE_GET_STATUS_KEY
  • INVOICE_GET_OUTPUTS_KEY

Optional

  • POLL_INTERVAL_SECONDS (default 10)
  • POLL_MAX_ATTEMPTS (default 24)
  • DEFAULT_COUNTRY_HINT (default JP)

Conversation store

  • CONVERSATION_STORE=memory|table (default memory)
  • AZURE_STORAGE_CONNECTION_STRING (required when CONVERSATION_STORE=table)
  • CONVERSATION_TABLE_NAME (required when CONVERSATION_STORE=table)
  • CONVERSATION_PARTITION_KEY (required when CONVERSATION_STORE=table)

Azure OpenAI (optional — the agent falls back to rule-based intent detection if unset)

  • AZURE_OPENAI_ENDPOINT
  • AZURE_OPENAI_API_KEY
  • AZURE_OPENAI_DEPLOYMENT
  • AZURE_OPENAI_API_VERSION (default 2024-10-21)
  • AZURE_OPENAI_AUTH_HEADER (api-key or bearer, default api-key)

Conversation-store modes:

  • Local development: CONVERSATION_STORE=memory.
  • Azure Container Apps production: CONVERSATION_STORE=table recommended (the table is auto-created if missing).

The Storage Table never persists: contentBase64, SAS-signed downloadUrl, Function keys, CROO_SDK_KEY, or AZURE_OPENAI_API_KEY.


Local setup

  1. Install dependencies:

    npm install
  2. Create .env from .env.example.

  3. Type-check:

    npm run typecheck
  4. Build:

    npm run build
  5. Start the provider:

    npm run dev

Local testing

Invoice API only:

npm run test:invoice-local -- ./path/to/file.jpg

Agent chat (bypasses CROO, uses a mock invoice client):

npm run test:agent-chat

Conversational multi-file real-send test:

npm run test:agent-chat-multifile -- "<file1>" "<file2>" "<file3>"

Azure OpenAI / Foundry Responses API connectivity:

npm run test:azure-openai

Azure OpenAI / Foundry auth troubleshooting

  1. Run npm run test:azure-openai with AZURE_OPENAI_AUTH_HEADER=api-key.
  2. If you get 401, switch to AZURE_OPENAI_AUTH_HEADER=bearer.
  3. Re-run npm run test:azure-openai.
  4. Keep the working mode, then run npm run test:agent-chat.

Docker

Build:

docker build -t croo-provider-invoice .

Run:

docker run --rm --env-file .env croo-provider-invoice

Deploy to Azure Container Apps

  1. Create the agent in the CROO Dashboard and copy CROO_API_KEY from the Configure Agent screen into .env.

  2. Set the Azure Functions / Table Storage / Azure OpenAI values in .env.

  3. Deploy:

    .\scripts\deploy-azure-containerapps.ps1
  4. Check logs:

    az containerapp logs show --name ca-croo-invoice-provider --resource-group rg-croo-hackathon --follow

Notes:

  • The deploy script reads .env first and registers secrets as Container Apps secrets.

  • CROO_API_KEY and CROO_SDK_KEY reference the same secret.

  • To ship a code-only update to an existing environment:

    .\scripts\update-azure-containerapps.ps1
  • For a temporary, CROO-independent HTTP test, enable the test endpoint:

    .\scripts\update-azure-containerapps.ps1 -EnableTempTestHttp -TestHttpToken "<temporary-token>"
    • Endpoint: https://<container-app-fqdn>/test/invoice-agent-chat
    • Header: x-test-token: <temporary-token>
    • Inspect a conversation: GET https://<container-app-fqdn>/test/conversations/<conversationId> (requires x-test-token)
    • When done, redeploy without -EnableTempTestHttp to close the public test path.
  • With PROVIDER_ACCESS_MODE=private, requests are rejected unless ALLOWED_BUYER_IDS / ALLOWED_WALLET_ADDRESSES are set appropriately.

  • Setting min replicas=0 for cost savings may prevent the always-on CROO WebSocket listener from staying connected.

  • Rotate CROO / Azure keys before going to production.


Security notes

  • Never commit Function keys, SDK keys, OpenAI keys, or Storage connection strings.
  • Never log contentBase64.
  • Never log full SAS-signed downloadUrls at INFO level.
  • Never log Function keys, OpenAI keys, or the CROO SDK key.
  • Prefer sourceUrl over contentBase64 for large files.

License

MIT © 2026 Masaaki Sogabe

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages