Create Chat Model
Every chat model takes a credential, a model name, and an optional provider-specificParameters object. The three tabs below show typical setups for streaming, tool calling, and reasoning:
Call Chat Model
Invoke the model by calling it with a list ofMsg objects, plus optional tools and tool_choice:
stream setting:
stream=False: awaits a singleChatResponsecarrying the full output.stream=True: awaits anAsyncGenerator[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.
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 (raisingasyncio.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:
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, callgenerate_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’sMsg 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:
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
SubclassCredentialBase with a unique type discriminator and implement get_chat_model_class():
Step 2: Implement the Chat Model
SubclassChatModelBase, 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: