MCPcopy
hub / github.com/dataelement/Clawith / send_message

Function send_message

backend/app/api/gateway.py:473–653  ·  view source on GitHub ↗

OpenClaw agent sends a message to a person or another agent. Routes automatically based on target type: - Agent target: triggers LLM processing, reply returned via next poll - Human target: sends via available channel (feishu, etc.)

(
    body: GatewaySendMessageRequest,
    x_api_key: str = Header(..., alias="X-Api-Key"),
    db: AsyncSession = Depends(get_db),
)

Source from the content-addressed store, hash-verified

471
472@router.post("/send-message")
473async def send_message(
474 body: GatewaySendMessageRequest,
475 x_api_key: str = Header(..., alias="X-Api-Key"),
476 db: AsyncSession = Depends(get_db),
477):
478 """OpenClaw agent sends a message to a person or another agent.
479
480 Routes automatically based on target type:
481 - Agent target: triggers LLM processing, reply returned via next poll
482 - Human target: sends via available channel (feishu, etc.)
483 """
484 agent = await _get_agent_by_key(x_api_key, db)
485 agent.openclaw_last_seen = datetime.now(timezone.utc)
486
487 target_name = body.target.strip()
488 content = body.content.strip()
489 channel_hint = (body.channel or "").strip().lower()
490
491 # 1. Try to find target as another Agent, limited to active relationships.
492 from app.models.org import AgentAgentRelationship
493 from sqlalchemy.orm import selectinload
494
495 rel_result = await db.execute(
496 select(AgentAgentRelationship)
497 .where(AgentAgentRelationship.agent_id == agent.id)
498 .options(selectinload(AgentAgentRelationship.target_agent))
499 )
500 target_agent = None
501 for rel in rel_result.scalars().all():
502 candidate = rel.target_agent
503 if not candidate:
504 continue
505 status_info = await evaluate_agent_relationship_status(db, rel)
506 if status_info["access_status"] != "active":
507 continue
508 if candidate.name.lower() == target_name.lower() or target_name.lower() in candidate.name.lower():
509 target_agent = candidate
510 break
511
512 logger.info(f"[Gateway] send_message: target='{target_name}', found_agent={target_agent.name if target_agent else None}, agent_type={getattr(target_agent, 'agent_type', None) if target_agent else None}, channel_hint='{channel_hint}'")
513
514 if target_agent and (not channel_hint or channel_hint == "agent"):
515 conv_id = f"gw_agent_{agent.id}_{target_agent.id}"
516
517 if getattr(target_agent, 'agent_type', None) == 'openclaw':
518 # OpenClaw-to-OpenClaw: write to gateway_messages directly
519 gw_msg = GatewayMessage(
520 agent_id=target_agent.id,
521 sender_agent_id=agent.id,
522 content=content,
523 status="pending",
524 conversation_id=conv_id,
525 )
526 db.add(gw_msg)
527 await db.commit()
528 return {
529 "status": "accepted",
530 "target": target_agent.name,

Callers

nothing calls this directly

Calls 15

GatewayMessageClass · 0.90
_get_agent_by_keyFunction · 0.85
optionsMethod · 0.80
whereMethod · 0.80
executeMethod · 0.45
allMethod · 0.45
scalarsMethod · 0.45
addMethod · 0.45
commitMethod · 0.45

Tested by

no test coverage detected