Advanced: for real-time integrations. Requires an active
instance.listen stream. If the stream is not active, this call raises ListeningNotActiveError.send_message() publishes a single agent activity event onto the bidirectional gRPC stream that listen() established. Each event tells the Synap platform what just happened in your agent (a user turn, an assistant reply, a tool call, or an explicit context request) so the platform can anticipate what context the agent will need next and push it back over the stream.
What the platform does with the event
Only
user_message and assistant_message become conversation history. Tool
calls, tool results and reasoning are short-lived hints for anticipation: never
compacted, never extracted into long-term memory, and held for at most seven
days in the debugging trail.
Persisted turns feed both layers of context. They advance the conversation toward automatic context compaction once it crosses the configured token or message threshold, and that same compaction promotes the raw turns into long-term memory.
Parameters
string
required
The message content. For
user_message and assistant_message events this is the natural-language turn; for tool_call events it can be a short description of the tool invocation.string
default:"user"
Either
"user" or "assistant".string
External identifier for the conversation this event belongs to. Required to associate the event with the right conversation scope. Must be a valid UUID registered via
record_message.string
External user identifier. Omit for customer- or client-scope events.
string
External customer identifier. Required on B2B. Not accepted on B2C: passing it is rejected with HTTP 400. See B2C vs B2B.
string
External session identifier.
string
default:"user_message"
The kind of event being reported, from the table above. An unrecognised value is refused with an error naming the real ones, rather than travelling to the server to be ignored there.
dict[str, str]
Additional string key-value metadata attached to the event.
string
For
tool_call events: the name of the tool the agent is invoking. The platform uses this to classify the tool call and anticipate the agent’s next data needs.any
For
tool_result events: what the tool returned. JSON-encodable, or a plain string.string
Ties a
tool_result to the tool_call that asked for it.dict
For
tool_call events: a JSON-encodable arguments dict for the tool invocation.list[string]
For
tool_call or context_request events: the retrieval queries the agent plans to run. Used as direct anticipation hints.list[string]
For
tool_call or context_request events: the memory categories the agent plans to fetch.Returns
ReturnsNone. The coroutine resolves once the event has been written to the stream.
Example
A whole turn, in order
The five kinds of event a turn produces, with the typed methods where they exist. The typed methods setevent_type and role together, which is the
pair that has to agree.
No session call anywhere in that turn. The SDK opens one on the first event
and closes it when you stop listening. Call
end_session yourself only when a
conversation ends and your process keeps running.Raises
ListeningNotActiveError: wheninstance.listenhas not been called or the stream has been closed.
See also
- Real-Time Anticipation: how streaming and ingestion fit together.
- instance.listen: open the stream this method writes to.
- instance.stop_listening: close the stream.
- instance.record_thinking, record_tool_call, record_tool_result: typed methods that set the role for you.
- Event delivery: ids, acknowledgements, retries, and the HTTP route.
- memories.create: the call that actually creates memories.