Skip to content

ckit_ask_model

The ckit_ask_model module provides functions for activating bots, creating subchats, and manipulating thread messages.

Bot Activation

bot_activate()

Start a new conversation with a bot:

from flexus_client_kit import ckit_ask_model
result = await ckit_ask_model.bot_activate(
client=fclient,
who_is_asking="my_service",
persona_id=rcx.persona.persona_id,
first_question="Analyze this data: ...",
title="Data Analysis",
fexp_name="analyst", # Optional: specific expert
)
print(f"Thread created: {result.ft_id}")

Parameters

ParameterTypeDescription
clientFlexusClientAPI client
who_is_askingstrIdentifier for logging
persona_idstrTarget bot’s persona ID
first_questionstrInitial message
titlestrThread title
fexp_namestrExpert name (default: “default”)
first_callstrOptional initial tool call JSON
context_fileslistFiles to include as context

Returns

FThreadOutput with:

  • ft_id — Thread ID
  • ft_title — Thread title
  • ft_need_assistant — Waiting for LLM response

Subchats

Subchats are isolated conversations that run in parallel and return results to the parent tool call.

bot_subchat_create_multiple()

Create one or more subchats:

from flexus_client_kit import ckit_ask_model, ckit_cloudtool
@rcx.on_tool_call("analyze_multiple")
async def handle(toolcall, args):
items = args["items"] # ["item1", "item2", "item3"]
subchats = await ckit_ask_model.bot_subchat_create_multiple(
client=fclient,
who_is_asking="multi_analyzer",
persona_id=rcx.persona.persona_id,
first_question=[f"Analyze: {item}" for item in items],
first_calls=["null" for _ in items], # No initial tool calls
title=[f"Analysis: {item}" for item in items],
fcall_id=toolcall.fcall_id,
fexp_name="analyst",
)
# This pauses until all subchats complete
raise ckit_cloudtool.WaitForSubchats(subchats)

Parameters

ParameterTypeDescription
clientFlexusClientAPI client
who_is_askingstrIdentifier for logging
persona_idstrBot’s persona ID
first_questionList[str]Initial messages (one per subchat)
first_callsList[str]Initial tool calls JSON (“null” for none)
titleList[str]Titles for each subchat
fcall_idstrParent tool call ID
fexp_namestrExpert to use

Returns

List[FThreadOutput] — Created subchat threads.

Subchat Completion

Subchats must complete within 10 minutes. The subchat expert’s Lark kernel must set subchat_result to signal completion. Without this, subchats will timeout.

Subchat Lark Kernel

The expert used for subchats needs a kernel that sets subchat_result:

# In install script, expert definition:
FMarketplaceExpertInput(
fexp_system_prompt=ANALYST_PROMPT,
fexp_python_kernel="""
# Check if analysis is complete
msg = messages[-1]
if msg["role"] == "assistant" and "ANALYSIS_COMPLETE" in str(msg.get("content", "")):
subchat_result = msg["content"]
elif msg["role"] == "assistant" and not msg.get("tool_calls"):
# No tool calls and no marker = ask to complete
post_cd_instruction = "Finish your analysis and include ANALYSIS_COMPLETE at the end."
""",
fexp_app_capture_tools=tools_json,
)

Message Operations

thread_messages_create_multiple()

Add messages to a thread:

await ckit_ask_model.thread_messages_create_multiple(
client=fclient,
ft_id=thread_id,
messages=[
{"role": "user", "content": "Additional context"},
{"role": "context_file", "content": "File contents here..."},
],
)

Message Roles

RolePurpose
userUser input
assistantBot response
toolTool call result
cd_instructionInjected instruction (from kernel)
context_fileFile/document context

Data Structures

FThreadOutput

@dataclass
class FThreadOutput:
ft_id: str # Thread ID
ft_title: str # Thread title
ft_need_assistant: int # >0 if waiting for LLM
ft_need_tool_calls: int # >0 if waiting for tools
ft_need_user: int # >0 if waiting for user
ft_error: str # Error message if any
ft_coins: int # Coins spent
ft_budget: int # Budget limit
ft_fexp_id: str # Expert ID
ft_toolset: str # JSON of allowed tools

FThreadMessageOutput

@dataclass
class FThreadMessageOutput:
ftm_id: str # Message ID
ftm_ft_id: str # Thread ID
ftm_role: str # Message role
ftm_content: str # Message content
ftm_tool_calls: List # Tool calls (for assistant)
ftm_call_id: str # Tool call ID (for tool results)
ftm_provenance: str # JSON metadata
ftm_created_ts: datetime

Patterns

Parallel Analysis with Subchats

@rcx.on_tool_call("deep_research")
async def handle(toolcall, args):
topic = args["topic"]
# Create 3 parallel research threads
subchats = await ckit_ask_model.bot_subchat_create_multiple(
client=fclient,
who_is_asking="deep_researcher",
persona_id=rcx.persona.persona_id,
first_question=[
f"Research academic sources on: {topic}",
f"Research industry reports on: {topic}",
f"Research news and trends on: {topic}",
],
first_calls=["null", "null", "null"],
title=["Academic", "Industry", "News"],
fcall_id=toolcall.fcall_id,
fexp_name="researcher",
)
raise ckit_cloudtool.WaitForSubchats(subchats)

Scheduled Bot Activation

# External service activates a bot on schedule
async def daily_report_trigger():
await ckit_ask_model.bot_activate(
client=fclient,
who_is_asking="daily_scheduler",
persona_id=report_bot_persona_id,
first_question="Generate daily sales report for yesterday",
title=f"Daily Report {date.today()}",
)

Sequential Chat with Context

# First message starts the thread
result = await ckit_ask_model.bot_activate(
client=fclient,
who_is_asking="workflow",
persona_id=rcx.persona.persona_id,
first_question="Start processing",
title="Workflow",
)
# Wait for response...
# Add more context
await ckit_ask_model.thread_messages_create_multiple(
client=fclient,
ft_id=result.ft_id,
messages=[
{"role": "context_file", "content": document_content},
{"role": "user", "content": "Now analyze the document above"},
],
)

Complete Example

from flexus_client_kit import ckit_ask_model, ckit_cloudtool
COMPARE_TOOL = ckit_cloudtool.CloudTool(
strict=True,
name="compare_options",
description="Compare multiple options in parallel",
parameters={
"type": "object",
"properties": {
"options": {
"type": "array",
"items": {"type": "string"},
"description": "Options to compare",
},
"criteria": {
"type": "string",
"description": "Comparison criteria",
},
},
"required": ["options", "criteria"],
"additionalProperties": False,
},
)
async def main_loop(fclient, rcx):
@rcx.on_tool_call(COMPARE_TOOL.name)
async def handle_compare(toolcall, args):
options = args["options"]
criteria = args["criteria"]
if len(options) < 2:
return "Need at least 2 options to compare"
if len(options) > 5:
return "Maximum 5 options allowed"
# Create parallel evaluation subchats
subchats = await ckit_ask_model.bot_subchat_create_multiple(
client=fclient,
who_is_asking="option_comparator",
persona_id=rcx.persona.persona_id,
first_question=[
f"Evaluate '{opt}' against criteria: {criteria}. "
f"Score 1-10 and explain. End with EVALUATION_COMPLETE."
for opt in options
],
first_calls=["null" for _ in options],
title=[f"Evaluate: {opt}" for opt in options],
fcall_id=toolcall.fcall_id,
fexp_name="evaluator", # Must have kernel that sets subchat_result
)
raise ckit_cloudtool.WaitForSubchats(subchats)
# Main loop
while not ckit_shutdown.shutdown_event.is_set():
await rcx.unpark_collected_events(sleep_if_no_work=10.0)