Skip to main content
An LLM (called a chat model in AgentScope’s class names) drives an agent’s conversation and tool calls, accepting and producing multimodal content beyond plain text. AgentScope currently ships the following chat model classes:

Create Chat Model

Every chat model takes a credential, a model name, and an optional provider-specific Parameters object. The three tabs below show typical setups for streaming, tool calling, and reasoning:
Common constructor arguments shared by every chat model:

Call Chat Model

Invoke the model by calling it with a list of Msg objects, plus optional tools and tool_choice:
The return type follows the model’s stream setting:
  • stream=False: awaits a single ChatResponse carrying the full output.
  • stream=True: awaits an AsyncGenerator[ChatResponse, None]. Intermediate chunks (is_last=False) carry only the delta generated in that step. The final chunk (is_last=True) carries the full accumulated content.
The two tabs below show both modes side by side:
A representative streaming trace, illustrating the delta-then-accumulated pattern:
Each ChatResponse carries content blocks (TextBlock, ThinkingBlock, ToolCallBlock, DataBlock), an is_last flag, a finished_reason (FinishedReason.COMPLETED or FinishedReason.INTERRUPTED), and a ChatUsage recording token counts and elapsed time.

Interrupt Model Call

Interruption at the model layer means asynchronous cancellation: a model call runs inside an asyncio task, and cancelling that task (raising asyncio.CancelledError) stops the in-flight API request, typically because the user interrupted the agent while it was reasoning. Instead of discarding the partial output, ChatModelBase.__call__ catches the cancellation and returns a final ChatResponse carrying the content accumulated so far, marked with finished_reason=FinishedReason.INTERRUPTED. Normal completions end with FinishedReason.COMPLETED, so downstream code can always distinguish a complete answer from a truncated one:
This is the model-layer half of agent interruption: the Agent class builds on the same mechanism to stop a running reasoning-acting loop and keep its context consistent. See Interrupt Agent for the agent-level behavior.

Generate Structured Output

When you need a JSON object that conforms to a Pydantic model or JSON schema, call generate_structured_output instead of __call__. It returns a StructuredResponse whose content is a validated dict matching the schema:
generate_structured_output synthesizes a forced tool call from the schema, then validates and repairs the model’s response.

Formatter

A formatter translates AgentScope’s Msg objects into the list[dict] payload that each provider’s API expects. It is configured via the optional formatter argument on the chat model constructor. Every provider ships two built-in variants: Switch to multi-agent mode by passing the MultiAgent variant; no agent code changes are required:
For non-standard payload shapes (e.g. a provider whose API doesn’t follow the OpenAI or Anthropic conventions), subclass FormatterBase and pass an instance through the same formatter argument.

Custom Provider

You can extend AgentScope with your own model provider by implementing a credential and a chat model, then registering the credential.

Step 1: Define the Credential

Subclass CredentialBase with a unique type discriminator and implement get_chat_model_class():

Step 2: Implement the Chat Model

Subclass ChatModelBase, define a Parameters inner class, and implement _call_api. The base class owns retry, streaming accumulation, and interruption handling, so _call_api only needs to translate provider responses into AgentScope ChatResponse chunks:
For streaming custom providers, yield provider deltas as ChatResponse(content=..., is_last=False). If _call_api ends without yielding a final is_last=True chunk, ChatModelBase.__call__ will accumulate the deltas with ChatResponse.append_chat_response() and emit the final response automatically. If the stream is cancelled, it emits the partial accumulated response with finished_reason=FinishedReason.INTERRUPTED.

Step 3: Add Model Cards (optional)

Drop YAML files into a _models/ directory next to your model implementation. Each file describes one model: its capabilities (input_types, output_types), limits (context_size, output_size), and any per-model parameter_overrides (see Integrate with Frontend for the full card format):
MyProviderChatModel.list_models() then loads every YAML in that directory. To pull cards from a different location (for example, a registry your application maintains separately), pass custom_yaml_dir: