Model or dataset
JC0v0/Customer-Agent avatar
JC0v0/Customer-Agent

Customer-Agent: a PyQt6 desktop agent for Pinduoduo storefronts

电商智能客服系统,支持AI客服回复,关键词转人工

968 stars239 forksPythonLicense varies

At a glance

What is it?
Customer-Agent is a Windows desktop application that connects to a Pinduoduo seller account over WebSocket and lets a large language model reply to buyers, hand off to a human on keywords, and pull product knowledge from two retrieval indexes. It is a single merchant channel wrapped in a Qt interface, not a general contact centre.
Who is it for?
Customer-Agent suits a seller who runs a Pinduoduo storefront, works on Windows and wants an answer bot that can be handed a product card mid conversation, and it does not suit anyone who needs several marketplaces, a web widget or a server deployment, since the only channel implemented is the Pinduoduo WebSocket feed.
Can I use it commercially?
Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
Is it still maintained?
Yes. The repository last received commits 31 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A desktop app aimed at one marketplace rather than a contact centre

Customer-Agent describes itself as an e-commerce AI customer service desktop application built on PyQt6, with multi channel integration and automatic replies driven by a large language model. The scope is much narrower than the description of a contact centre suggests. The feature list states that multi channel support currently covers the Pinduoduo platform with real time WebSocket message reception, and only that.

The interface is a desktop application rather than a service. The readme explains that ordinary users do not need to configure a Python environment and can download an installer, roughly 100 MB, from the GitHub releases page and run it. It installs into the user directory without administrator rights, ships a Chinese wizard, and creates a desktop shortcut. The installer bundles the Playwright driver, so when an account is added the application drives the Chrome or Edge browser already installed on the machine to complete the login rather than asking the user to install Playwright or Chromium.

That last point is the design decision worth noting. Instead of talking to the marketplace API with a token, the app authenticates by driving a real browser session. It is a workable way to reuse an interactive login, and it also means the app inherits everything that comes with automating a logged in browser session on a machine you control.

Five tools are the entire surface the agent can act on

The agent framework is custom written, and the readme states explicitly that it does not depend on Agno. The tool table is short and concrete, which makes the capability envelope easy to reason about. There is `get_shop_products` to list shop products with filters for price range, sales, stock and tags, `send_goods_link` to send a product card link to the buyer, `get_product_knowledge` to look up details on a specific product such as ingredients, specifications, usage and price, `search_customer_service_knowledge` to search the service knowledge base for after sales, logistics and refund policy questions, and `transfer_conversation` to hand the conversation to a human agent.

Two of those five act on the conversation rather than only fetching data, so the model is not limited to text replies. It can pull the product list and then push a card to the customer in the middle of a conversation, which is the proactive recommendation feature the readme lists separately.

Keyword based hand-off to a human is handled separately from the tool call, by a keyword handler that identifies user intent and triggers the transfer. The message pipeline is described as an asynchronous queue plus a chain of processors, with the project layout listing preprocessor, AI and keyword handlers under `Message/handlers/`. So the same conversation can be routed by a deterministic keyword match even when the model decides it could keep going.

Two knowledge bases, one for products and one for policy

Product knowledge and service knowledge are kept apart and retrieved separately. The product index holds item information and answers questions about a specific product, while the customer service index holds after sales, logistics and refund policy material. Search over the service base uses `jieba` for Chinese word segmentation, and token counting is handled by `tiktoken`.

The product side is populated automatically. The readme describes a sync routine that pulls the product list from the Pinduoduo API and calls a multimodal large language model to extract product knowledge into the index. So the product base starts empty on a new install and fills itself from the shop catalogue, using a vision capable model to read images as part of extraction. Document parsing is also in the dependency list, with `pypdf`, `python-docx`, `openpyxl` and `xlrd`, which suggests imported spreadsheets and documents are another way product and policy material can enter the system.

Storage is local. The technical stack table names SQLAlchemy with SQLite, and the layout puts the database, the knowledge service and the product sync under `database/`. There is no server component to host, no Postgres to run and no vector store to operate, which suits a single operator but caps the scale at one machine.

LiteLLM fronts six model providers, with strict endpoint rules

Model access goes through LiteLLM, called directly on Chat Completions, so no LiteLLM Proxy has to be started. The settings page offers six providers, each with a routing prefix and a default base URL: DeepSeek at `https://api.deepseek.com`, Volcengine at `https://ark.cn-beijing.volces.com/api/v3`, OpenAI-compatible with no default, Moonshot at `https://api.moonshot.cn/v1`, Z.AI at `https://open.bigmodel.cn/api/paas/v4` and Qwen via DashScope at `https://dashscope.aliyuncs.com/compatible-mode/v1`. The OpenAI-compatible entry is the escape hatch for an internal model, and the readme says the model name there can be anything, including an organisation internal model name.

Endpoint validation is the most opinionated part of the documentation. Remote endpoints must use HTTPS with certificate verification intact. URLs carrying embedded credentials, cloud instance metadata addresses and link local addresses are rejected, as are redirects that cross hosts. Local or private endpoints such as Ollama or LM Studio on the same machine or the local network are allowed to use HTTP, but only after the option to allow local or private endpoints is explicitly selected in the settings page.

The readme is also careful about tool calling. A custom endpoint or a model whose capabilities are unknown makes the settings page show an unverified state and require explicit confirmation of the provider, model, endpoint and tool policy. A model that clearly does not support tool calls cannot be enabled, and the application does not silently disable the tools. The project version in pyproject.toml pins `litellm==1.96.2`, so the LiteLLM behaviour is fixed rather than floating.

Installing from source and pointing it at a model provider

The readme lists Python 3.11 or newer and a Windows operating system, noting that the packaged executable runs standalone on Windows. Dependencies are installed with uv.

bash
uv sync

The application then starts from the entry point at the repository root.

bash
python app.py

On first run a `config.json` file is generated. The readme recommends entering the API key under the system settings for LLM model configuration, and states that the samples, the logs and the CI do not need environment variables and contain no real keys. Each provider needs a model identifier and an API key filled in by hand.

Two details are worth planning around. First, API keys are protected with Windows DPAPI before being written to disk, so the encrypted value is tied to the Windows user account on that machine. Second, saving a provider profile only affects new accounts. Accounts that are already running keep their own profile snapshot, and only the existing stop and restart procedure moves them onto the new configuration.

Old configurations are migrated on load. A profile without `llm.provider` is rewritten: historical Ark and Volcengine endpoints become `volcengine`, and any other unrecognised custom endpoint becomes `openai_compatible`, with model name, endpoint and API key left unchanged.

Tags drive the Windows installer build through CI

Packaging is a two step pipeline. On Windows, a build script packages the application with PyInstaller, producing a `dist/AgentCustomer/` directory that includes the bundled Playwright driver, and then calls Inno Setup to compress it into a single installer at `dist/installer/Agent-Customer-Setup-<version>.exe`.

bash
python scripts/build_win_exe.py --clean

The version number is read from the most recent git tag with the leading `v` removed, and the `APP_VERSION` environment variable can override it. If only the PyInstaller onedir output is needed without the installer, the `--skip-installer` flag does that.

CI takes the same path automatically. Pushing a tag in the `v*` format triggers GitHub Actions to build and publish a release, and the resulting `Agent-Customer-Setup-<version>.exe` is attached to that tag's release page, which is the same page the download instructions point ordinary users at.

bash
git tag v1.4
git push origin v1.4

One loose end sits in the version metadata. The pyproject.toml declares `version = "1.1.0"` while the published releases reached v1.6.0 on 2026-09-22 and v1.5 on 2026-09-21. The build script takes the version from the git tag rather than from pyproject.toml, so the packaged installer gets the right number, but the packaged metadata inside the wheel and the sdist would not.

Windows only, one channel, and no documented rollback

The hard limits are plain. The application targets Windows, and the packaging path is PyInstaller plus Inno Setup, so the install by double clicking story does not exist on Linux or macOS. The only implemented channel is Pinduoduo, so a seller with meaningful volume on other marketplaces gains nothing from it. And the whole product knowledge pipeline starts from a live Pinduoduo API call, so a shop that does not expose that catalogue to the tool has nothing to describe.

There is also a boundary around the model provider that will not be obvious from the marketing. The agent's useful behaviour depends on tool calling, and a provider that does not support tool calls cannot be enabled at all. On an internal network, where the only reachable endpoint is HTTP, the private endpoint option has to be switched on by hand before the app will talk to it.

One thing the readme is unusually candid about is data leaving the machine. Product sync sends the necessary product text and images to the chosen provider, and it states plainly that the retention, training and cross border transfer policies on the provider side are the user's own responsibility to confirm. It also says the application never sends the API key, cookies, authorization headers or internal profile fields. The readme does not document a rollback path for a bad product sync, no migration notes for the SQLite schema, and no way to export the knowledge bases, so the local data directory is effectively the system of record.

Where a hosted helpdesk differs from a desktop bot

The usual alternative to a tool like this is a hosted customer service platform with a web widget your visitors use directly, plus human agent tooling behind it. The difference in approach is where the conversation happens and who controls the data.

A hosted platform runs server side, so it serves many shoppers at once, keeps conversation history in a database you can query, and survives the merchant closing the laptop. Customer-Agent runs on one Windows desktop, holds its data in a local SQLite file, and keeps working only while the machine is on and the logged in browser session is alive. The user interface is the application itself, with system settings for provider configuration rather than an operations console for supervising conversations.

The trade runs the other way on control. Here the shop owner decides which model provider receives product data, can point the agent at an internal OpenAI-compatible endpoint, and can inspect the SQLite database directly. A hosted service will generally not route to a private model. What you give up is availability and the ability to hand a conversation to a staffed agent queue, since `transfer_conversation` hands off to a human within the desktop application rather than to a ticketing system. For a single seller with predictable questions, the local approach is coherent. For a shop with peak hours, shift work or a need for conversation history, the local database and the single running machine become the limiting factor.

Editorial conclusion

Customer-Agent suits a seller who runs a Pinduoduo storefront, works on Windows and wants an answer bot that can be handed a product card mid conversation, and it does not suit anyone who needs several marketplaces, a web widget or a server deployment, since the only channel implemented is the Pinduoduo WebSocket feed. Before adopting it, confirm that your storefront credentials work through the bundled Playwright driven browser login, check whether the account you need to serve is covered by the five exposed tools, and read the version numbers first, because pyproject.toml still declares 1.1.0 while the last release tag was v1.6.0 on 2026-09-22.

Frequently asked questions

How do I install Customer-Agent?

Ordinary users download `Agent-Customer-Setup-<version>.exe` from the latest GitHub releases page and run it, which installs to the user directory without administrator rights. To run from source on Windows with Python 3.11 or newer, use `uv sync` and then `python app.py`.

Which platforms does Customer-Agent support?

The readme lists Windows as the supported operating system and Python 3.11 or newer as the requirement for source builds. The packaging path is PyInstaller plus Inno Setup, producing a Windows installer.

Which model providers can Customer-Agent talk to?

The settings page offers DeepSeek, Volcengine, OpenAI-compatible, Kimi/Moonshot, Z.AI and Qwen/DashScope, reached through LiteLLM on Chat Completions without a separate proxy. Every provider needs a model identifier and an API key entered by hand, and models that do not support tool calls cannot be enabled.

How does Customer-Agent transfer a conversation to a human?

The agent exposes a `transfer_conversation` tool, and a separate keyword handler detects intent from the buyer's message and triggers the transfer to a human agent. The transfer happens inside the desktop application rather than in an external ticketing system.

How is the product knowledge base filled in?

Product knowledge is synced from the Pinduoduo API: the shop product list is pulled and a multimodal large language model extracts product knowledge into the index. The index is stored locally through SQLAlchemy with SQLite, and the service knowledge base holds after sales, logistics and refund policy material searched with jieba.

Official sources

  1. Issues
  2. JC0v0/Customer-Agent on GitHub
  3. README
  4. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/jc0v0-customer-agent.svg)](https://hysenlabs.com/projects/jc0v0-customer-agent)

Was this useful?